"use strict";
/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const GBEMU_DURATION = 0.000020833333110203966;
const GBEMU_0 = 0;
const GBEMU_1 = 1;
const GBEMU_2 = 2;
const GBEMU_3 = 3;
const GBEMU_4 = 4;
const GBEMU_5 = 5;
const GBEMU_6 = 6;
const GBEMU_7 = 7;
const GBEMU_8 = 8;
const GBEMU_9 = 9;
const GBEMU_10 = 10;
const GBEMU_11 = 11;
const GBEMU_12 = 12;
const GBEMU_13 = 13;
const GBEMU_14 = 14;
const GBEMU_15 = 15;
const GBEMU_16 = 16;
const GBEMU_17 = 17;
const GBEMU_18 = 18;
const GBEMU_19 = 19;
const GBEMU_20 = 20;
const GBEMU_21 = 21;
const GBEMU_22 = 22;
const GBEMU_23 = 23;
const GBEMU_24 = 24;
const GBEMU_25 = 25;
const GBEMU_26 = 26;
const GBEMU_27 = 27;
const GBEMU_28 = 28;
const GBEMU_29 = 29;
const GBEMU_30 = 30;
const GBEMU_31 = 31;
const GBEMU_32 = 32;
const GBEMU_33 = 33;
const GBEMU_34 = 34;
const GBEMU_35 = 35;
const GBEMU_36 = 36;
const GBEMU_37 = 37;
const GBEMU_38 = 38;
const GBEMU_39 = 39;
const GBEMU_40 = 40;
const GBEMU_88 = 88;
const GBEMU_90 = 90;
const GBEMU_41 = 41;
const GBEMU_42 = 42;
const GBEMU_43 = 43;
const GBEMU_44 = 44;
const GBEMU_45 = 45;
const GBEMU_46 = 46;
const GBEMU_47 = 47;
const GBEMU_48 = 48;
const GBEMU_49 = 49;
const GBEMU_50 = 50;
const GBEMU_51 = 51;
const GBEMU_52 = 52;
const GBEMU_53 = 53;
const GBEMU_54 = 54;
const GBEMU_55 = 55;
const GBEMU_56 = 56;
const GBEMU_57 = 57;
const GBEMU_58 = 58;
const GBEMU_59 = 59;
const GBEMU_60 = 60;
const GBEMU_61 = 61;
const GBEMU_62 = 62;
const GBEMU_63 = 63;
const GBEMU_72 = 72;
const GBEMU_80 = 80;
const GBEMU_64 = 64;
const GBEMU_96 = 96;
const GBEMU_127 = 127;
const GBEMU_128 = 128;
const GBEMU_144 = 144;
const GBEMU_160 = 160;
const GBEMU_225 = 225;
const GBEMU_252 = 252;
const GBEMU_256 = 256;
const GBEMU_512 = 512;
const GBEMU_1000 = 1000;
const GBEMU_1024 = 1024;
const GBEMU_1985 = 1985;
const GBEMU_4096 = 4096;
const GBEMU_456 = 456;
const GBEMU_298 = 298;
const GBEMU_143 = 143;
const GBEMU_154 = 154;
const GBEMU_168 = 168;
const GBEMU_74 = 74;
const GBEMU_82 = 82;
const GBEMU_222 = 222;
const GBEMU_255 = 255;
const GBEMU_239 = 239;
const GBEMU_69120 = 69120;
const GBEMU_248 = 248;
const GBEMU_153 = 153;
const GBEMU_312 = 312;
const GBEMU_5016 = 5016;
const GBEMU_100 = 100;
const GBEMU_2047 = 2047;
const GBEMU_8192 = 8192;
const GBEMU_92160 = 92160;
const GBEMU_250000 = 250000;
const GBEMU_15000 = 15000;
const GBEMU_44100 = 44100;
const GBEMU_25000 = 25000;
const GBEMU_23040 = 23040;
const GBEMU_27044 = 27044;
const GBEMU_48000 = 48000;
const GBEMU_0xFF50 = 0xff50;
const GBEMU_0x50 = 0x50;
const GBEMU_0xFF6C = 0xff6c;
const GBEMU_0x6C = 0x6c;
const GBEMU_0x143 = 0x143;
const GBEMU_0xFF74 = 0xff74;
const GBEMU_0x74 = 0x74;
const GBEMU_0xFF70 = 0xff70;
const GBEMU_0x70 = 0x70;
const GBEMU_0x10 = 0x10;
const GBEMU_0xFF6B = 0xff6b;
const GBEMU_0x6B = 0x6b;
const GBEMU_0xFF6A = 0xff6a;
const GBEMU_0x6A = 0x6a;
const GBEMU_0xFF69 = 0xff69;
const GBEMU_0x69 = 0x69;
const GBEMU_0xFF68 = 0xff68;
const GBEMU_0x68 = 0x68;
const GBEMU_0xFF55 = 0xff55;
const GBEMU_0x55 = 0x55;
const GBEMU_0xFF4F = 0xff4f;
const GBEMU_0x4F = 0x4f;
const GBEMU_0x4D = 0x4d;
const GBEMU_0xFF4D = 0xff4d;
const GBEMU_0x49 = 0x49;
const GBEMU_0xFF49 = 0xff49;
const GBEMU_0x48 = 0x48;
const GBEMU_0x1 = 0x1;
const GBEMU_0xFF48 = 0xff48;
const GBEMU_0xFF47 = 0xff47;
const GBEMU_0x47 = 0x47;
const GBEMU_0xFEA0 = 0xfea0;
const GBEMU_0xFF46 = 0xff46;
const GBEMU_0x46 = 0x46;
const GBEMU_0xFE00 = 0xfe00;
const GBEMU_0x41 = 0x41;
const GBEMU_0xFF41 = 0xff41;
const GBEMU_0x2 = 0x2;
const GBEMU_0x08 = 0x08;
const GBEMU_0x20 = 0x20;
const GBEMU_0x40 = 0x40;
const GBEMU_0xE0 = 0xe0;
const GBEMU_0x7F = 0x7f;
const GBEMU_0x78 = 0x78;
const GBEMU_0xFF40 = 0xff40;
const GBEMU_0x01 = 0x01;
const GBEMU_0x02 = 0x02;
const GBEMU_0x04 = 0x04;
const GBEMU_0x400 = 0x400;
const GBEMU_0x80 = 0x80;
const GBEMU_0xFF44 = 0xff44;
const GBEMU_0xFF02 = 0xff02;
const GBEMU_0xD000 = 0xd000;
const GBEMU_0xE000 = 0xe000;
const GBEMU_0x2000 = 0x2000;
const GBEMU_0x07 = 0x07;
const GBEMU_0xFF51 = 0xff51;
const GBEMU_0xFF52 = 0xff52;
const GBEMU_0x3F = 0x3f;
const GBEMU_0xFF = 0xff;
const GBEMU_0xFF54 = 0xff54;
const GBEMU_0x54 = 0x54;
const GBEMU_0xF0 = 0xf0;
const GBEMU_0x53 = 0x53;
const GBEMU_0xFF53 = 0xff53;
const GBEMU_0x52 = 0x52;
const GBEMU_0x51 = 0x51;
const GBEMU_0x7f = 0x7f;
const GBEMU_0xff = 0xff;
const GBEMU_0xFFFFFF = 0xffffff;
const GBEMU_0x00 = 0x00;
const GBEMU_0x13 = 0x13;
const GBEMU_0xD8 = 0xd8;
const GBEMU_0x014D = 0x014d;
const GBEMU_0xFFFE = 0xfffe;
const GBEMU_0x0100 = 0x0100;
const GBEMU_0xA000 = 0xa000;
const GBEMU_0xF000 = 0xf000;
const GBEMU_0xEFFFDE = 0xefffde;
const GBEMU_0xADD794 = 0xadd794;
const GBEMU_0x529273 = 0x529273;
const GBEMU_0x183442 = 0x183442;
const GBEMU_0x0F = 0x0f;
const GBEMU_0x7C = 0x7c;
const GBEMU_0xF8 = 0xf8;
const GBEMU_0xBF = 0xbf;
const GBEMU_0xF3 = 0xf3;
const GBEMU_0x77 = 0x77;
const GBEMU_0xF1 = 0xf1;
const GBEMU_0xFC = 0xfc;
const GBEMU_0x3E = 0x3e;
const GBEMU_0x9F = 0x9f;
const GBEMU_0x7E = 0x7e;
const GBEMU_0xFE = 0xfe;
const GBEMU_0x91 = 0x91;
const GBEMU_0x8F = 0x8f;
const GBEMU_0xC0 = 0xc0;
const GBEMU_0x0B = 0x0b;
const GBEMU_0xDC = 0xdc;
const GBEMU_0xDD = 0xdd;
const GBEMU_0x03 = 0x03;
const GBEMU_0xCE = 0xce;
const GBEMU_0xED = 0xed;
const GBEMU_0xC1 = 0xc1;
const GBEMU_0xE6 = 0xe6;
const GBEMU_0x83 = 0x83;
const GBEMU_0x6E = 0x6e;
const GBEMU_0x99 = 0x99;
const GBEMU_0x3D = 0x3d;
const GBEMU_0x36 = 0x36;
const GBEMU_0xD3 = 0xd3;
const GBEMU_0x45 = 0x45;
const GBEMU_0xBB = 0xbb;
const GBEMU_0xD0 = 0xd0;
const GBEMU_0x98 = 0x98;
const GBEMU_0x7A = 0x7a;
const GBEMU_0xEC = 0xec;
const GBEMU_0xEF = 0xef;
const GBEMU_0xD1 = 0xd1;
const GBEMU_0x67 = 0x67;
const GBEMU_0x66 = 0x66;
const GBEMU_0x1F = 0x1f;
const GBEMU_0xCC = 0xcc;
const GBEMU_0x0D = 0x0d;
const GBEMU_0x63 = 0x63;
const GBEMU_0x89 = 0x89;
const GBEMU_0xB7 = 0xb7;
const GBEMU_0xC2 = 0x11;
const GBEMU_0x11 = 0x11;
const GBEMU_0x71 = 0x71;
const GBEMU_0xFA = 0xfa;
const GBEMU_0x88 = 0x88;
const GBEMU_0xF4 = 0xf4;
const GBEMU_0x9E = 0x9e;
const GBEMU_0xF9 = 0xf9;
const GBEMU_0x0E = 0x0e;
const GBEMU_0x86 = 0x86;
const GBEMU_0x5F = 0x5f;
const GBEMU_0x24 = 0x24;
const GBEMU_0x5D = 0x5d;
const GBEMU_0x73 = 0x73;
const GBEMU_0xFD = 0xfd;
const GBEMU_0x6D = 0x6d;
const GBEMU_0x12 = 0x12;
const GBEMU_0x1D = 0x1d;
const GBEMU_0x2F = 0x2f;
const GBEMU_0x75 = 0x75;
const GBEMU_0x05 = 0x05;
const GBEMU_0x81 = 0x81;
const GBEMU_0xB4 = 0xb4;
const GBEMU_0x0C = 0x0c;
const GBEMU_0xB9 = 0xb9;
const GBEMU_0xD9 = 0xd9;
const GBEMU_0x33 = 0x33;
const GBEMU_0x97 = 0x97;
const GBEMU_0xE5 = 0xe5;
const GBEMU_0x5E = 0x5e;
const GBEMU_0x06 = 0x06;
const GBEMU_0xD5 = 0xd5;
const GBEMU_0xAA = 0xaa;
const GBEMU_0x3A = 0x3a;
const GBEMU_0x418 = 0x418;
const GBEMU_0x7FFF = 0x7fff;
const GBEMU_0x200 = 0x200;
const GBEMU_0x800 = 0x800;
const GBEMU_0x100 = 0x100;
const GBEMU_0xFFFF = 0xffff;
const GBEMU_0xF = 0xf;
const GBEMU_0xFFF = 0xfff;
const GBEMU_0x60 = 0x60;
const GBEMU_0x26 = 0x26;
const GBEMU_0xFF26 = 0xff26;
const GBEMU_0xFF27 = 0xff27;
const GBEMU_0xFF28 = 0xff28;
const GBEMU_0xFF29 = 0xff29;
const GBEMU_0xFF2A = 0xff2a;
const GBEMU_0xFF2B = 0xff2b;
const GBEMU_0xFF2C = 0xff2c;
const GBEMU_0xFF2D = 0xff2d;
const GBEMU_0xFF2E = 0xff2e;
const GBEMU_0xFF2F = 0xff2f;
const GBEMU_0xFF30 = 0xff30;
const GBEMU_0xFF31 = 0xff31;
const GBEMU_0xFF32 = 0xff32;
const GBEMU_0xFF33 = 0xff33;
const GBEMU_0xFF34 = 0xff34;
const GBEMU_0xFF35 = 0xff35;
const GBEMU_0xFF36 = 0xff36;
const GBEMU_0xFF37 = 0xff37;
const GBEMU_0xFF38 = 0xff38;
const GBEMU_0xFF39 = 0xff39;
const GBEMU_0xFF3A = 0xff3a;
const GBEMU_0xFF3B = 0xff3b;
const GBEMU_0xFF3C = 0xff3c;
const GBEMU_0xFF3D = 0xff3d;
const GBEMU_0xFF3E = 0xff3e;
const GBEMU_0xFF3F = 0xff3f;
const GBEMU_0xFF00 = 0xff00;
const GBEMU_0xFF42 = 0xff42;
const GBEMU_0x42 = 0x42;
const GBEMU_0xFF43 = 0xff43;
const GBEMU_0x43 = 0x43;
const GBEMU_0x44 = 0x44;
const GBEMU_0xFF4A = 0xff4a;
const GBEMU_0x4A = 0x4a;
const GBEMU_0xFF56 = 0xff56;
const GBEMU_0x3C = 0x3c;
const GBEMU_0x56 = 0x56;
const GBEMU_0x6c = 0x6c;
const GBEMU_0xFF75 = 0xff75;
const GBEMU_0xFF76 = 0xff76;
const GBEMU_0xFF77 = 0xff77;
const GBEMU_0xA060 = 0xa060;
const GBEMU_0xA070 = 0xa070;
const GBEMU_0xA080 = 0xa080;
const GBEMU_0xA050 = 0xa050;
const GBEMU_0xA040 = 0xa040;
const GBEMU_0xA030 = 0xa030;
const GBEMU_0xA020 = 0xa020;
const GBEMU_0x09 = 0x09;
const GBEMU_0x0A = 0x0a;
const GBEMU_0x0000 = 0x0000;
const GBEMU_0x8000 = 0x8000;
const GBEMU_0x4000 = 0x4000;
const GBEMU_0x6000 = 0x6000;
const GBEMU_0x1000 = 0x1000;
const GBEMU_0x2100 = 0x2100;
const GBEMU_0x2200 = 0x2200;
const GBEMU_0x3000 = 0x3000;
const GBEMU_0x9000 = 0x9000;
const GBEMU_0x9800 = 0x9800;
const GBEMU_0xC000 = 0xc000;
const GBEMU_0x1FFF = 0x1fff;
const GBEMU_0xA200 = 0xa200;
const GBEMU_0x7FF = 0x7ff;
const GBEMU_0x1800 = 0x1800;
const GBEMU_0x8001 = 0x8001;
const GBEMU_0x8002 = 0x8002;
const GBEMU_0x8003 = 0x8003;
const GBEMU_0x8004 = 0x8004;
const GBEMU_0x8005 = 0x8005;
const GBEMU_0x8006 = 0x8006;
const GBEMU_0x8007 = 0x8007;
const GBEMU_0x8008 = 0x8008;
const GBEMU_0x8009 = 0x8009;
const GBEMU_0x800A = 0x800a;
const GBEMU_0x800B = 0x800b;
const GBEMU_0x800C = 0x800c;
const GBEMU_0x800D = 0x800d;
const GBEMU_0x800E = 0x800e;
const GBEMU_0x800F = 0x800f;
const GBEMU_0x7F0 = 0x7f0;
const GBEMU_0x1FF0 = 0x1ff0;
const GBEMU_0xFFF0 = 0xfff0;
const GBEMU_0x3 = 0x3;
const GBEMU_0x4 = 0x4;
const GBEMU_0x5 = 0x5;
const GBEMU_0x6 = 0x6;
const GBEMU_0x7 = 0x7;
const GBEMU_0x8 = 0x8;
const GBEMU_0x9 = 0x9;
const GBEMU_0xA = 0xa;
const GBEMU_0xB = 0xb;
const GBEMU_0xC = 0xc;
const GBEMU_0xD = 0xd;
const GBEMU_0xE = 0xe;
const GBEMU_0x30 = 0x30;
const GBEMU_0xFF01 = 0xff01;
const GBEMU_0xFF04 = 0xff04;
const GBEMU_0xFF05 = 0xff05;
const GBEMU_0xFF06 = 0xff06;
const GBEMU_0xFF07 = 0xff07;
const GBEMU_0xFF0F = 0xff0f;
const GBEMU_0xFF10 = 0xff10;
const GBEMU_0xFF11 = 0xff11;
const GBEMU_0xFF12 = 0xff12;
const GBEMU_0xFF13 = 0xff13;
const GBEMU_0xFF14 = 0xff14;
const GBEMU_0x700 = 0x700;
const GBEMU_0x0 = 0x0;
const GBEMU_0x14 = 0x14;
const GBEMU_0xFF16 = 0xff16;
const GBEMU_0x16 = 0x16;
const GBEMU_0xFF17 = 0xff17;
const GBEMU_0x17 = 0x17;
const GBEMU_0xFF18 = 0xff18;
const GBEMU_0x18 = 0x18;
const GBEMU_0xFF19 = 0xff19;
const GBEMU_0x19 = 0x19;
const GBEMU_0xFF1A = 0xff1a;
const GBEMU_0x1A = 0x1a;
const GBEMU_0xFF1B = 0xff1b;
const GBEMU_0x1B = 0x1b;
const GBEMU_0xFF1C = 0xff1c;
const GBEMU_0x1C = 0x1c;
const GBEMU_0xFF1D = 0xff1d;
const GBEMU_0xFF1E = 0xff1e;
const GBEMU_0x1E = 0x1e;
const GBEMU_0x21 = 0x21;
const GBEMU_0x22 = 0x22;
const GBEMU_0x23 = 0x23;
const GBEMU_0x25 = 0x25;
const GBEMU_0x27 = 0x27;
const GBEMU_0x28 = 0x28;
const GBEMU_0x29 = 0x29;
const GBEMU_0xFF20 = 0xff20;
const GBEMU_0xFF21 = 0xff21;
const GBEMU_0xFF22 = 0xff22;
const GBEMU_0xFF23 = 0xff23;
const GBEMU_0xFF24 = 0xff24;
const GBEMU_0xFF25 = 0xff25;
const GBEMU_0x2A = 0x2a;
const GBEMU_0x2B = 0x2b;
const GBEMU_0x2C = 0x2c;
const GBEMU_0x2E = 0x2e;
const GBEMU_0x2D = 0x2d;
const GBEMU_0x31 = 0x31;
const GBEMU_0x32 = 0x32;
const GBEMU_0x34 = 0x34;
const GBEMU_0x35 = 0x35;
const GBEMU_0x37 = 0x37;
const GBEMU_0x38 = 0x38;
const GBEMU_0x39 = 0x39;
const GBEMU_0x3B = 0x3b;
const GBEMU_0xFF45 = 0xff45;
const GBEMU_0xFF4B = 0xff4b;
const GBEMU_0x4B = 0x4b;
const GBEMU_0xFF72 = 0xff72;
const GBEMU_0xFF73 = 0xff73;
const GBEMU_0x72 = 0x72;
const GBEMU_0x76 = 0x76;
const GBEMU_0x0080 = 0x0080;
const GBEMU_0x0001 = 0x0001;
const GBEMU_0xFF80 = 0xff80;
const GBEMU_0xF00 = 0xf00;
const GBEMU_0x0200 = 0x0200;
const GBEMU_0x0002 = 0x0002;
const GBEMU_0x0400 = 0x0400;
const GBEMU_0x0004 = 0x0004;
const GBEMU_0x0800 = 0x0800;
const GBEMU_0x0008 = 0x0008;
const GBEMU_0x0010 = 0x0010;
const GBEMU_0x0020 = 0x0020;
const GBEMU_0x0040 = 0x0040;
const GBEMU_0xFEFF = 0xfeff;
const GBEMU_0xFDFF = 0xfdff;
const GBEMU_0xFFFD = 0xfffd;
const GBEMU_0xFF1F = 0xff1f;
const GBEMU_0x600 = 0x600;
const GBEMU_0x1FFE = 0x1ffe;
const GBEMU_0x9FFE = 0x9ffe;
const GBEMU_0xA00 = 0xa00;
const GBEMU_0xC00 = 0xc00;
const GBEMU_0xE00 = 0xe00;
const GBEMU_0x1000000 = 0x1000000;
const GBEMU_0x2000000 = 0x2000000;
const GBEMU_0x1f = 0x1f;
const GBEMU_0xf80 = 0xf80;
const GBEMU_0xF8F8F8 = 0xf8f8f8;
const GBEMU_0x7B = 0x7b;
const GBEMU_0xf = 0xf;
const GBEMU_0xF7 = 0xf7;
const GBEMU_0xFB = 0xfb;
const GBEMU_0xF0F0 = 0xf0f0;
const GBEMU_0x1FF = 0x1ff;
const GBEMU_0x10000 = 0x10000;
const GBEMU_0x780 = 0x780;
const GBEMU_0x680 = 0x680;
const GBEMU_0x500 = 0x500;
const GBEMU_0x580 = 0x580;
const GBEMU_0x480 = 0x480;
const GBEMU_0x380 = 0x380;
const GBEMU_0x300 = 0x300;
const GBEMU_0x280 = 0x280;
const GBEMU_0x180 = 0x180;
const GBEMU_0x080 = 0x080;
const GBEMU_0x78000 = 0x78000;
const GBEMU_0x70000 = 0x70000;
const GBEMU_0x68000 = 0x68000;
const GBEMU_0x60000 = 0x60000;
const GBEMU_0x58000 = 0x58000;
const GBEMU_0x50000 = 0x50000;
const GBEMU_0x48000 = 0x48000;
const GBEMU_0x40000 = 0x40000;
const GBEMU_0x38000 = 0x38000;
const GBEMU_0x30000 = 0x30000;
const GBEMU_0x28000 = 0x28000;
const GBEMU_0x20000 = 0x20000;
const GBEMU_0x18000 = 0x18000;
const GBEMU_0x08000 = 0x08000;
const GBEMU_0x3FFF = 0x3fff;
const GBEMU_0x80000 = 0x80000;
const GBEMU_0x400000 = 0x400000;
const GBEMU_0x7000 = 0x7000;
const GBEMU_0x7D = 0x7d;
const GBEMU_0x900 = 0x900;
const GBEMU_0x144 = 0x144;
const GBEMU_0x145 = 0x145;
const GBEMU_0x14B = 0x14b;
const GBEMU_0x148 = 0x148;
const GBEMU_0x149 = 0x149;
const GBEMU_0x7ff = 0x7ff;
const GBEMU_0xfe = 0xfe;
const GBEMU_0x1fff = 0x1fff;
const GBEMU_0xC3 = 0xc3;
const GBEMU_0xFFFFFFFF = 0xffffffff;
const GBEMU_0xFFFFFFFE = 0xfffffffe;
const GBEMU_0x9A = 0x9a;
const GBEMU_0xA0 = 0xa0;
const GBEMU_0x80FF = 0x80ff;
const GBEMU_0xFBFF = 0xfbff;
const GBEMU_0xFFFB = 0xfffb;
const GBEMU_0xF7FF = 0xf7ff;
const GBEMU_0xFFF7 = 0xfff7;
const GBEMU_0xEFFF = 0xefff;
const GBEMU_0xFFEF = 0xffef;
const GBEMU_0xDF = 0xdf;
const GBEMU_0xDFFF = 0xdfff;
const GBEMU_0xFFDF = 0xffdf;
const GBEMU_0xBFFF = 0xbfff;
const GBEMU_0xFFBF = 0xffbf;
const GBEMU_0xFF7F = 0xff7f;
const GBEMU_0x101 = 0x101;
const GBEMU_0x134 = 0x134;
const GBEMU_0x13F = 0x13f;
const GBEMU_0x147 = 0x147;
// ------ gbemu-part1 ------
let decodedGameboyRom = '';
/*
 * @State
 * @Tags Jetstream2
 */
class Benchmark {
    /*
     * @Setup
     */
    setupGameboy() {
        initializeWebKitAudio();
        decodedGameboyRom = base64Decode(gameboyRom);
    }
    /*
     * @Benchmark
     */
    runGameboy() {
        //debugLog('This is runGameboy')
        start(new GameBoyCanvas(), decodedGameboyRom);
        gameboy.instructions = 0;
        gameboy.totalInstructions = GBEMU_250000;
        while (gameboy.instructions <= gameboy.totalInstructions) {
            //debugLog(`This is runGameboy instructions: ${gameboy!.instructions}`);
            gameboy.run();
            gameBoyAudioNode.run();
        }
        resetGlobalVariables();
    }
    /*
     * @Teardown
     */
    tearDownGameboy() {
        decodedGameboyRom = '';
        expectedGameboyStateStr = '';
    }
}
let expectedGameboyStateStr = `{'registerA':160,'registerB':255,'registerC':255,'registerE':11,'registersHL':51600,'programCounter':24309,'stackPointer':49706,'sumrom':10171578,'sumMemory':3435856,'summbcRam':234598,'sumVRam':0}`;
// Start of browser emulation.
class GameBoyWindowClass {
    constructor() {
        this.opera = false;
        this.mozRequestAnimationFrame = false;
    }
}
let gameBoyWindow = new GameBoyWindowClass();
class GameBoyContext {
    createImageData(w, h) {
        let result = new GameBoyContextImageDataResult();
        result.data = new Uint8Array(w * h * GBEMU_4);
        return result;
    }
    putImageData(buffer, x, y) {
        let sum = 0;
        for (let i = 0; i < buffer.data.length; i++) {
            sum += i * buffer.data[i];
            sum = sum % GBEMU_1000;
        }
    }
    drawImage(canvas, x, y, screenWidth, screenHeight) { }
}
class GameBoyContextImageDataResult {
    constructor() {
        this.data = new Uint8Array();
    }
}
class GameBoyCanvas {
    constructor() {
        this.width = GBEMU_160;
        this.height = GBEMU_144;
        this.clientWidth = 0;
        this.clientHeight = 0;
        this.style = new GameBoyCanvasStyle();
    }
    getContext(type) {
        return new GameBoyContext();
    }
}
class GameBoyCanvasStyle {
    constructor() {
        this.visibility = 'visibile';
    }
}
function cout(message, colorIndex) { }
class GameBoyAudioNodeConstrc {
    constructor() {
        this.bufferSize = 0;
        this.outputBuffer = null;
        this.onaudioprocess = null;
    }
    connect(destination) { }
    run() {
        let event = new GameBoyAudioNodeEvent();
        event.outputBuffer = this.outputBuffer;
        this.onaudioprocess(event);
    }
}
let gameBoyAudioNode = new GameBoyAudioNodeConstrc();
class GameBoyAudioNodeEvent {
    constructor() {
        this.outputBuffer = null;
    }
}
class GameBoyAudioNodeBuffer {
    constructor() {
        this.channelData = [];
    }
    getChannelData(i) {
        return this.channelData[i];
    }
}
class GameBoyAudioContext {
    constructor() {
        this.sampleRate = GBEMU_48000;
        this.destination = new GameBoyAudioContextDestination();
    }
    createBufferSource() {
        return new GameBoyAudioContextBufferSource();
    }
    createBuffer(channels, len, sampleRate) {
        return new GameBoyAudioContextBuffer(1, 1, 1, GBEMU_DURATION, GBEMU_48000);
    }
    createJavaScriptNode(bufferSize, inputChannels, outputChannels) {
        gameBoyAudioNode.bufferSize = bufferSize;
        gameBoyAudioNode.outputBuffer = new GameBoyAudioNodeBuffer();
        for (let i = 0; i < outputChannels; i++) {
            gameBoyAudioNode.outputBuffer.channelData[i] = new Float32Array(bufferSize);
        }
        return gameBoyAudioNode;
    }
}
class GameBoyAudioContextBufferSource {
    constructor() {
        this.loop = false;
        this.buffer = null;
    }
    noteOn(index) { }
    connect(audioNode) { }
}
class GameBoyAudioContextDestination {
}
class GameBoyAudioContextBuffer {
    constructor(gain, numberOfChannels, length, duration, sampleRate) {
        this.gain = gain;
        this.numberOfChannels = numberOfChannels;
        this.length = length;
        this.duration = duration;
        this.sampleRate = sampleRate;
    }
}
let mockDateTimeCounter = 0;
class NewDate {
    getTime() {
        mockDateTimeCounter += GBEMU_16;
        return mockDateTimeCounter;
    }
}
// End of browser emulation.
// Start of helper functions.
function checkFinalState() {
    let stateStr = `{'registerA':${gameboy.registerA},'registerB':${gameboy.registerB},'registerC':${gameboy.registerC},'registerE':${gameboy.registerE},'registersHL':${gameboy.registersHL},'programCounter':${gameboy.programCounter},'stackPointer':${gameboy.stackPointer},'sumrom':${setStateSum(gameboy.fromTypedArray(gameboy.rom))},'sumMemory':${setStateSum(gameboy.fromTypedArray(gameboy.memory))},'summbcRam':${setStateSum(gameboy.fromTypedArray(gameboy.mbcRam))},'sumVRam':${setStateSum(gameboy.fromTypedArray(gameboy.vram))}}`;
    if (expectedGameboyStateStr.length > 0) {
        if (stateStr !== expectedGameboyStateStr) {
        }
    }
    else {
    }
}
function setStateSum(a) {
    let result = 0;
    for (let i = 0; i < a.length; i++) {
        result += a[i];
    }
    return result;
}
function resetGlobalVariables() {
    //debugLog('This is resetGlobalVariables');
    //Audio API Event Handler:
    audioContextHandle = null;
    audioNode = null;
    audioSource = null;
    launchedContext = false;
    audioContextSampleBuffer = new Float32Array();
    resampled = new Float32Array();
    webAudioMinBufferSize = GBEMU_15000;
    webAudioMaxBufferSize = GBEMU_25000;
    webAudioActualSampleRate = GBEMU_44100;
    xAudioJSSampleRate = 0;
    webAudioMono = false;
    xAudioJSVolume = 1;
    resampleControl = null;
    audioBufferSize = 0;
    resampleBufferStart = 0;
    resampleBufferEnd = 0;
    resampleBufferSize = GBEMU_2;
    gameboy = null; //GameBoyCore object.
}
// End of helper functions.
// Original code from Grant Galitz follows.
// Modifications by Google are marked in comments.
// Start of js/other/base64.js file.
let toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
let base64Pad = '=';
/* Convert Base64 data to a string */
let toBinaryTable = [
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, GBEMU_62, -1, -1, -1, GBEMU_63, GBEMU_52, GBEMU_53, GBEMU_54, GBEMU_55, GBEMU_56, GBEMU_57, GBEMU_58, GBEMU_59, GBEMU_60, GBEMU_61, -1, -1, -1, 0, -1, -1, -1, 0, 1, GBEMU_2, GBEMU_3, GBEMU_4, GBEMU_5, GBEMU_6, GBEMU_7, GBEMU_8, GBEMU_9, GBEMU_10, GBEMU_11, GBEMU_12, GBEMU_13, GBEMU_14, GBEMU_15, GBEMU_16, GBEMU_17, GBEMU_18, GBEMU_19, GBEMU_20, GBEMU_21, GBEMU_22, GBEMU_23, GBEMU_24, GBEMU_25, -1, -1, -1, -1, -1, -1, GBEMU_26, GBEMU_27, GBEMU_28, GBEMU_29, GBEMU_30, GBEMU_31, GBEMU_32, GBEMU_33, GBEMU_34, GBEMU_35, GBEMU_36, GBEMU_37, GBEMU_38, GBEMU_39, GBEMU_40, GBEMU_41, GBEMU_42, GBEMU_43, GBEMU_44, GBEMU_45, GBEMU_46, GBEMU_47, GBEMU_48, GBEMU_49, GBEMU_50, GBEMU_51, -1, -1, -1, -1, -1
];
function base64Decode(data) {
    let result = '';
    let leftbits = 0; // number of bits decoded, but yet to be appended
    let leftdata = 0; // bits decoded, but yet to be appended
    for (let i = 0; i < data.length; i++) {
        let c = toBinaryTable[data.charCodeAt(i) & GBEMU_0x7f];
        let padding = data.charCodeAt(i) === base64Pad.charCodeAt(0);
        // Skip illegal characters and whitespace
        if (c === -1)
            continue;
        // Collect data into leftdata, update bitcount
        leftdata = (leftdata << GBEMU_6) | c;
        leftbits += GBEMU_6;
        // If we have GBEMU_8 or more bits, append GBEMU_8 bits to the result
        if (leftbits >= GBEMU_8) {
            leftbits -= GBEMU_8;
            // Append if not padding.
            if (!padding) {
                result += String.fromCharCode((leftdata >> leftbits) & GBEMU_0xff);
            }
            leftdata &= (1 << leftbits) - 1;
        }
    }
    return result;
}
// End of js/other/base64.js file.
// Start of js/other/resampler.js file.
//JavaScript Audio Resampler (c) 2011 - Grant Galitz
class Resampler {
    constructor(fromSampleRate, toSampleRate, channels = 0, outputBufferSize, noReturn) {
        this.fromSampleRate = 0;
        this.toSampleRate = 0;
        this.channels = 0;
        this.outputBufferSize = 0;
        this.noReturn = false;
        this.resampler = () => new Float32Array();
        this.ratioWeight = 0;
        this.tailExists = false;
        this.lastWeight = 0;
        this.lastOutput = new Float32Array();
        this.outputBuffer = new Float32Array();
        this.fromSampleRate = fromSampleRate;
        this.toSampleRate = toSampleRate;
        this.channels = channels | 0;
        this.outputBufferSize = outputBufferSize;
        this.noReturn = noReturn;
        this.initialize();
    }
    initialize() {
        //Perform some checks:
        if (this.fromSampleRate > 0 && this.toSampleRate > 0 && this.channels > 0) {
            if (this.fromSampleRate === this.toSampleRate) {
                //Setup a resampler bypass:
                this.resampler = this.bypassResampler; //Resampler just returns what was passed through.
                this.ratioWeight = 1;
            }
            else {
                //Setup the interpolation resampler:
                this.resampler = this.interpolate; //Resampler is a custom quality interpolation algorithm.
                this.ratioWeight = this.fromSampleRate / this.toSampleRate;
                this.tailExists = false;
                this.lastWeight = 0;
                this.initializeBuffers();
            }
        }
        else {
        }
    }
    interpolate(buffer) {
        let bufferLength = Math.min(buffer.length, this.outputBufferSize);
        if (bufferLength % GBEMU_2 === 0) {
            if (bufferLength > 0) {
                let ratioWeight = this.ratioWeight;
                let weight = 0;
                let output0 = 0;
                let output1 = 0;
                let actualPosition = 0;
                let amountToNext = 0;
                let alreadyProcessedTail = !this.tailExists;
                this.tailExists = false;
                let outputBuffer = this.outputBuffer;
                let outputOffset = 0;
                let currentPosition = 0;
                do {
                    if (alreadyProcessedTail) {
                        weight = ratioWeight;
                        output0 = 0;
                        output1 = 0;
                    }
                    else {
                        weight = this.lastWeight;
                        output0 = this.lastOutput[0];
                        output1 = this.lastOutput[1];
                        alreadyProcessedTail = true;
                    }
                    while (weight > 0 && actualPosition < bufferLength) {
                        amountToNext = 1 + actualPosition - currentPosition;
                        if (weight >= amountToNext) {
                            output0 += buffer[actualPosition++] * amountToNext;
                            output1 += buffer[actualPosition++] * amountToNext;
                            currentPosition = actualPosition;
                            weight -= amountToNext;
                        }
                        else {
                            output0 += buffer[actualPosition] * weight;
                            output1 += buffer[actualPosition + 1] * weight;
                            currentPosition += weight;
                            weight = 0;
                            break;
                        }
                    }
                    if (weight === 0) {
                        outputBuffer[outputOffset++] = output0 / ratioWeight;
                        outputBuffer[outputOffset++] = output1 / ratioWeight;
                    }
                    else {
                        this.lastWeight = weight;
                        this.lastOutput[0] = output0;
                        this.lastOutput[1] = output1;
                        this.tailExists = true;
                        break;
                    }
                } while (actualPosition < bufferLength);
                return this.bufferSlice(outputOffset);
            }
            else {
                return this.noReturn ? 0 : new Float32Array();
            }
        }
        else {
        }
        return new Float32Array();
    }
    bypassResampler(buffer) {
        if (this.noReturn) {
            //Set the buffer passed as our own, as we don't need to resample it:
            this.outputBuffer = buffer;
            return buffer.length;
        }
        else {
            //Just return the buffer passsed:
            return buffer;
        }
    }
    bufferSlice(sliceAmount) {
        if (this.noReturn) {
            //If we're going to access the properties directly from this object:
            return sliceAmount;
        }
        else {
            //Typed array and normal array buffer section referencing:
            return this.outputBuffer.subarray(0, sliceAmount);
        }
    }
    initializeBuffers() {
        //Initialize the internal buffer:
        this.outputBuffer = new Float32Array(this.outputBufferSize);
        this.lastOutput = new Float32Array(this.channels);
    }
}
// End of js/other/resampler.js file.
// Start of js/other/XAudioServer.js file.
/*Initialize here first:
  Example:
    Stereo audio with a sample rate of 70 khz, a minimum buffer of 15000 samples total, a maximum buffer of 25000 samples total and a starting volume level of 1.
      var parentObj = this;
      this.audioHandle = new XAudioServer(GBEMU_2, GBEMU_70000, GBEMU_15000, GBEMU_25000, function (sampleCount) {
        return parentObj.audioUnderRun(sampleCount);
      }, 1);

  The callback is passed the number of samples requested, while it can return any number of samples it wants back.
*/
class XAudioServer {
    constructor(channels = 0, sampleRate = 0, minBufferSize = 0, maxBufferSize = 0, underRunCallback, volume = 0) {
        this.audioChannels = 0;
        this.channels = 0;
        this.sampleRate = 0;
        this.minBufferSize = 0;
        this.maxBufferSize = 0;
        this.volume = 0;
        this.audioType = -1;
        this.mozAudioTail = [];
        this.audioHandleMoz = null;
        this.audioHandleFlash = null;
        this.flashInitialized = false;
        this.mozAudioFound = false;
        this.channels = channels;
        this.sampleRate = sampleRate;
        this.minBufferSize = minBufferSize;
        this.maxBufferSize = maxBufferSize;
        this.volume = volume;
        this.audioChannels = channels === GBEMU_2 ? GBEMU_2 : 1;
        webAudioMono = this.audioChannels === 1;
        xAudioJSSampleRate = sampleRate > 0 && sampleRate <= GBEMU_0xFFFFFF ? sampleRate : GBEMU_44100;
        webAudioMinBufferSize =
            minBufferSize >= samplesPerCallback << 1 && minBufferSize < maxBufferSize ?
                minBufferSize & (webAudioMono ? GBEMU_0xFFFFFFFF : GBEMU_0xFFFFFFFE) :
                samplesPerCallback << 1;
        webAudioMaxBufferSize =
            Math.floor(maxBufferSize) > webAudioMinBufferSize + this.audioChannels ?
                maxBufferSize & (webAudioMono ? GBEMU_0xFFFFFFFF : GBEMU_0xFFFFFFFE) :
                minBufferSize << 1;
        this.underRunCallback = typeof underRunCallback === 'function' ? underRunCallback : () => { };
        xAudioJSVolume = volume >= 0 && volume <= 1 ? volume : 1;
        this.initializeAudio();
    }
    callbackBasedWriteAudioNoCallback(buffer) {
        //Callback-centered audio APIs:
        let length = buffer.length;
        let bufferCounter = 0;
        while (bufferCounter < length && audioBufferSize < webAudioMaxBufferSize) {
            audioContextSampleBuffer[audioBufferSize++] = buffer[bufferCounter++];
        }
    }
    /*Pass your samples into here if you don't want automatic callback calling:
    Pack your samples as a one-dimenional array
    With the channel samplea packed uniformly.
    examples:
        mono - [left, left, left, left]
        stereo - [left, right, left, right, left, right, left, right]
    Useful in preventing infinite recursion issues with calling writeAudio inside your callback.
    */
    writeAudioNoCallback(buffer) {
        if (this.audioType === 0) {
        }
        else if (this.audioType === 1) {
            this.callbackBasedWriteAudioNoCallback(buffer);
        }
        else if (this.audioType === GBEMU_2) {
            if (this.checkFlashInit() || launchedContext) {
                this.callbackBasedWriteAudioNoCallback(buffer);
            }
            else if (this.mozAudioFound) {
            }
        }
    }
    //Developer can use this to see how many samples to write (example: minimum buffer allotment minus remaining samples left returned from this function to make sure maximum buffering is done...)
    //If -1 is returned, then that means metric could not be done.
    remainingBuffer() {
        if (this.audioType === 0) {
            //mozAudio:
        }
        else if (this.audioType === 1) {
            //WebKit Audio:
            return (((resampledSamplesLeft() * resampleControl.ratioWeight) >> (this.audioChannels - 1)) << (this.audioChannels - 1)) + audioBufferSize;
        }
        else if (this.audioType === GBEMU_2) {
            if (this.checkFlashInit() || launchedContext) {
                //Webkit Audio / Flash Plugin Audio:
                return (((resampledSamplesLeft() * resampleControl.ratioWeight) >> (this.audioChannels - 1)) << (this.audioChannels - 1)) + audioBufferSize;
            }
            else if (this.mozAudioFound) {
                //mozAudio:
            }
        }
        //Default return:
        return 0;
    }
    //DO NOT CALL THIS, the lib calls this internally!
    initializeAudio() {
        if (launchedContext) {
            this.initializeWebAudio();
        }
        else {
            this.initializeFlashAudio();
        }
    }
    initializeWebAudio() {
        resetCallbackAPIAudioBuffer(webAudioActualSampleRate, samplesPerCallback);
        this.audioType = 1;
    }
    changeVolume(newVolume) {
        if (newVolume >= 0 && newVolume <= 1) {
            xAudioJSVolume = newVolume;
            if (this.checkFlashInit()) {
            }
        }
    }
    initializeFlashAudio() { }
    //Checks to see if the NPAPI Adobe Flash bridge is ready yet:
    checkFlashInit() {
        return this.flashInitialized;
    }
}
class Audio {
}
/////////END LIB
function getFloat32(size) {
    return new Float32Array(size);
}
function getFloat32Flat(size) {
    return new Float32Array(size);
}
//Flash NPAPI Event Handler:
let samplesPerCallback = 2048; //Has to be between 2048 and 4096 (If over, then samples are ignored, if under then silence is added).
let outputConvert = null;
function generateFlashStereoString() {
    //Convert the arrays to one long string for speed.
    let copyBinaryStringLeft = '';
    let copyBinaryStringRight = '';
    let index = 0;
    while (index < samplesPerCallback && resampleBufferStart !== resampleBufferEnd) {
        //Sanitize the buffer:
        copyBinaryStringLeft += String.fromCharCode(((Math.min(Math.max(resampled[resampleBufferStart++] + 1, 0), GBEMU_2) * GBEMU_0x3FFF) | 0) + GBEMU_0x3000);
        copyBinaryStringRight += String.fromCharCode(((Math.min(Math.max(resampled[resampleBufferStart++] + 1, 0), GBEMU_2) * GBEMU_0x3FFF) | 0) + GBEMU_0x3000);
        if (resampleBufferStart === resampleBufferSize) {
            resampleBufferStart = 0;
        }
        index += 1;
    }
    return copyBinaryStringLeft + copyBinaryStringRight;
}
function generateFlashMonoString() {
    //Convert the array to one long string for speed.
    let copyBinaryString = '';
    let index = 0;
    while (index < samplesPerCallback && resampleBufferStart !== resampleBufferEnd) {
        //Sanitize the buffer:
        copyBinaryString += String.fromCharCode(((Math.min(Math.max(resampled[resampleBufferStart++] + 1, 0), GBEMU_2) * GBEMU_0x3FFF) | 0) + GBEMU_0x3000);
        if (resampleBufferStart === resampleBufferSize) {
            resampleBufferStart = 0;
        }
        index += 1;
    }
    return copyBinaryString;
}
//Audio API Event Handler:
let audioContextHandle = null;
let audioNode = null;
let audioSource = null;
let launchedContext = false;
let audioContextSampleBuffer = new Float32Array();
let resampled = new Float32Array();
let webAudioMinBufferSize = GBEMU_15000;
let webAudioMaxBufferSize = GBEMU_250000;
let webAudioActualSampleRate = GBEMU_44100;
let xAudioJSSampleRate = 0;
let webAudioMono = false;
let xAudioJSVolume = 1;
let resampleControl = null;
let audioBufferSize = 0;
let resampleBufferStart = 0;
let resampleBufferEnd = 0;
let resampleBufferSize = GBEMU_2;
function audioOutputEvent(event) {
    //Web Audio API callback...
    let index = 0;
    let buffer1 = event.outputBuffer.getChannelData(0);
    let buffer2 = event.outputBuffer.getChannelData(1);
    resampleRefill();
    if (!webAudioMono) {
        //STEREO:
        while (index < samplesPerCallback && resampleBufferStart !== resampleBufferEnd) {
            buffer1[index] = resampled[resampleBufferStart++] * xAudioJSVolume;
            buffer2[index++] = resampled[resampleBufferStart++] * xAudioJSVolume;
            if (resampleBufferStart === resampleBufferSize) {
                resampleBufferStart = 0;
            }
        }
    }
    else {
        //MONO:
        while (index < samplesPerCallback && resampleBufferStart !== resampleBufferEnd) {
            buffer1[index] = resampled[resampleBufferStart++] * xAudioJSVolume;
            buffer2[index] = buffer1[index];
            index += 1;
            if (resampleBufferStart === resampleBufferSize) {
                resampleBufferStart = 0;
            }
        }
    }
    //Pad with silence if we're underrunning:
    while (index < samplesPerCallback) {
        buffer1[index] = 0;
        buffer2[index] = 0;
        index += 1;
    }
}
function resampleRefill() {
    if (audioBufferSize > 0) {
        //Resample a chunk of audio:
        let resampleLength = resampleControl.resampler(getBufferSamples());
        let resampledResult = resampleControl.outputBuffer;
        for (let index2 = 0; index2 < resampleLength; ++index2) {
            resampled[resampleBufferEnd++] = resampledResult[index2];
            if (resampleBufferEnd === resampleBufferSize) {
                resampleBufferEnd = 0;
            }
            if (resampleBufferStart === resampleBufferEnd) {
                resampleBufferStart += 1;
                if (resampleBufferStart === resampleBufferSize) {
                    resampleBufferStart = 0;
                }
            }
        }
        audioBufferSize = 0;
    }
}
function resampledSamplesLeft() {
    return (resampleBufferStart <= resampleBufferEnd ? 0 : resampleBufferSize) + resampleBufferEnd - resampleBufferStart;
}
function getBufferSamples() {
    // Typed array and normal array buffer section referencing:
    return audioContextSampleBuffer.subarray(0, audioBufferSize);
}
//Initialize WebKit Audio /Flash Audio Buffer:
function resetCallbackAPIAudioBuffer(APISampleRate, bufferAlloc) {
    audioContextSampleBuffer = getFloat32(webAudioMaxBufferSize);
    audioBufferSize = webAudioMaxBufferSize;
    resampleBufferStart = 0;
    resampleBufferEnd = 0;
    resampleBufferSize = Math.max(webAudioMaxBufferSize * Math.ceil(xAudioJSSampleRate / APISampleRate), samplesPerCallback) << 1;
    if (webAudioMono) {
        //MONO Handling:
        resampled = getFloat32Flat(resampleBufferSize);
        resampleControl = new Resampler(xAudioJSSampleRate, APISampleRate, 1, resampleBufferSize, true);
        outputConvert = generateFlashMonoString;
    }
    else {
        //STEREO Handling:
        resampleBufferSize <<= 1;
        resampled = getFloat32Flat(resampleBufferSize);
        resampleControl = new Resampler(xAudioJSSampleRate, APISampleRate, GBEMU_2, resampleBufferSize, true);
        outputConvert = generateFlashStereoString;
    }
}
//Initialize WebKit Audio:
function initializeWebKitAudio() {
    //debugLog('This is initializeWebKitAudio')
    if (!launchedContext) {
        // The following line was modified for benchmarking:
        audioContextHandle = new GameBoyAudioContext(); //Create a system audio context.
        audioSource = audioContextHandle.createBufferSource(); //We need to create a false input to get the chain started.
        audioSource.loop = false; //Keep this alive forever (Event handler will know when to ouput.)
        xAudioJSSampleRate = audioContextHandle.sampleRate;
        webAudioActualSampleRate = audioContextHandle.sampleRate;
        audioSource.buffer = audioContextHandle.createBuffer(1, 1, webAudioActualSampleRate); //Create a zero'd input buffer for the input to be valid.
        audioNode = audioContextHandle.createJavaScriptNode(samplesPerCallback, 1, GBEMU_2); //Create GBEMU_2 outputs and ignore the input buffer (Just copy buffer 1 over if mono)
        audioNode.onaudioprocess = audioOutputEvent; //Connect the audio processing event to a handling function so we can manipulate output
        audioSource.connect(audioNode); //Send and chain the input to the audio manipulation.
        audioNode.connect(audioContextHandle.destination); //Send and chain the output of the audio manipulation to the system audio output.
        audioSource.noteOn(0); //Start the loop!
        launchedContext = true;
    }
}
// End of js/other/XAudioServer.js file.
// Start of js/other/resize.js file.
//JavaScript Image Resizer (c) 2012 - Grant Galitz
class Resize {
    constructor(widthOriginal, heightOriginal, targetWidth, targetHeight, blendAlpha, interpolationPass) {
        this.widthOriginal = 0;
        this.heightOriginal = 0;
        this.targetWidth = 0;
        this.targetHeight = 0;
        this.blendAlpha = false;
        this.colorChannels = 0;
        this.interpolationPass = false;
        this.targetWidthMultipliedByChannels = 0;
        this.originalWidthMultipliedByChannels = 0;
        this.originalHeightMultipliedByChannels = 0;
        this.widthPassResultSize = 0;
        this.finalResultSize = 0;
        this.resizeWidth = null;
        this.resizeHeight = null;
        this.ratioWeightWidthPass = 0;
        this.ratioWeightHeightPass = 0;
        this.outputWidthWorkBench = new Float32Array();
        this.widthBuffer = new Float32Array();
        this.outputHeightWorkBench = new Float32Array();
        this.heightBuffer = new Uint8Array();
        this.blendAlpha = blendAlpha;
        this.widthOriginal = Math.abs(Number.parseInt(String(widthOriginal)) || 0);
        this.heightOriginal = Math.abs(Number.parseInt(String(heightOriginal)) || 0);
        this.targetWidth = Math.abs(Number.parseInt(String(targetWidth)) || 0);
        this.targetHeight = Math.abs(Number.parseInt(String(targetHeight)) || 0);
        this.colorChannels = blendAlpha ? GBEMU_4 : GBEMU_3;
        this.interpolationPass = interpolationPass;
        this.targetWidthMultipliedByChannels = this.targetWidth * this.colorChannels;
        this.originalWidthMultipliedByChannels = this.widthOriginal * this.colorChannels;
        this.originalHeightMultipliedByChannels = this.heightOriginal * this.colorChannels;
        this.widthPassResultSize = this.targetWidthMultipliedByChannels * this.heightOriginal;
        this.finalResultSize = this.targetWidthMultipliedByChannels * this.targetHeight;
        this.initialize();
    }
    initialize() {
        //Perform some checks:
        if (this.widthOriginal > 0 && this.heightOriginal > 0 && this.targetWidth > 0 && this.targetHeight > 0) {
            if (this.widthOriginal === this.targetWidth) {
                //Bypass the width resizer pass:
                this.resizeWidth = this.bypassResizer;
            }
            else {
                //Setup the width resizer pass:
                this.ratioWeightWidthPass = this.widthOriginal / this.targetWidth;
                if (this.ratioWeightWidthPass < 1 && this.interpolationPass) {
                    this.initializeFirstPassBuffers(true);
                    this.resizeWidth = this.colorChannels === GBEMU_4 ? this.resizeWidthInterpolatedRGBA : this.resizeWidthInterpolatedRGB;
                }
                else {
                    this.initializeFirstPassBuffers(false);
                    this.resizeWidth = this.colorChannels === GBEMU_4 ? this.resizeWidthRGBA : this.resizeWidthRGB;
                }
            }
            if (this.heightOriginal === this.targetHeight) {
                //Bypass the height resizer pass:
                this.resizeHeight = this.bypassResizer;
            }
            else {
                //Setup the height resizer pass:
                this.ratioWeightHeightPass = this.heightOriginal / this.targetHeight;
                if (this.ratioWeightHeightPass < 1 && this.interpolationPass) {
                    this.initializeSecondPassBuffers(true);
                    this.resizeHeight = this.resizeHeightInterpolated;
                }
                else {
                    this.initializeSecondPassBuffers(false);
                    this.resizeHeight = this.colorChannels === GBEMU_4 ? this.resizeHeightRGBA : this.resizeHeightRGB;
                }
            }
        }
    }
    resizeWidthRGB(buffer) {
        let ratioWeight = this.ratioWeightWidthPass;
        let weight = 0;
        let amountToNext = 0;
        let actualPosition = 0;
        let currentPosition = 0;
        let line = 0;
        let pixelOffset = 0;
        let outputOffset = 0;
        let nextLineOffsetOriginalWidth = this.originalWidthMultipliedByChannels - GBEMU_2;
        let nextLineOffsetTargetWidth = this.targetWidthMultipliedByChannels - GBEMU_2;
        let output = this.outputWidthWorkBench;
        let outputBuffer = this.widthBuffer;
        do {
            line = 0;
            while (line < this.originalHeightMultipliedByChannels) {
                output[line++] = 0;
                output[line++] = 0;
                output[line++] = 0;
            }
            weight = ratioWeight;
            do {
                amountToNext = 1 + actualPosition - currentPosition;
                if (weight >= amountToNext) {
                    line = 0;
                    pixelOffset = actualPosition;
                    while (line < this.originalHeightMultipliedByChannels) {
                        output[line++] += buffer[pixelOffset++] * amountToNext;
                        output[line++] += buffer[pixelOffset++] * amountToNext;
                        output[line++] += buffer[pixelOffset] * amountToNext;
                        pixelOffset += nextLineOffsetOriginalWidth;
                    }
                    actualPosition = actualPosition + GBEMU_3;
                    currentPosition = actualPosition;
                    weight -= amountToNext;
                }
                else {
                    line = 0;
                    pixelOffset = actualPosition;
                    while (line < this.originalHeightMultipliedByChannels) {
                        output[line++] += buffer[pixelOffset++] * weight;
                        output[line++] += buffer[pixelOffset++] * weight;
                        output[line++] += buffer[pixelOffset] * weight;
                        pixelOffset += nextLineOffsetOriginalWidth;
                    }
                    currentPosition += weight;
                    break;
                }
            } while (weight > 0 && actualPosition < this.originalWidthMultipliedByChannels);
            line = 0;
            pixelOffset = outputOffset;
            while (line < this.originalHeightMultipliedByChannels) {
                outputBuffer[pixelOffset++] = output[line++] / ratioWeight;
                outputBuffer[pixelOffset++] = output[line++] / ratioWeight;
                outputBuffer[pixelOffset] = output[line++] / ratioWeight;
                pixelOffset += nextLineOffsetTargetWidth;
            }
            outputOffset += GBEMU_3;
        } while (outputOffset < this.targetWidthMultipliedByChannels);
        return outputBuffer;
    }
    resizeWidthInterpolatedRGB(buffer) {
        let ratioWeight = (this.widthOriginal - 1) / this.targetWidth;
        let weight = 0;
        let finalOffset = 0;
        let pixelOffset = 0;
        let outputBuffer = this.widthBuffer;
        let targetPosition = 0;
        while (targetPosition < this.targetWidthMultipliedByChannels) {
            //Calculate weightings:
            let secondWeight = weight % 1;
            let firstWeight = 1 - secondWeight;
            //Interpolate:
            finalOffset = targetPosition;
            pixelOffset = Math.floor(weight) * GBEMU_3;
            while (finalOffset < this.widthPassResultSize) {
                outputBuffer[finalOffset] = buffer[pixelOffset] * firstWeight + buffer[pixelOffset + GBEMU_3] * secondWeight;
                outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1] * firstWeight + buffer[pixelOffset + GBEMU_4] * secondWeight;
                outputBuffer[finalOffset + GBEMU_2] = buffer[pixelOffset + GBEMU_2] * firstWeight + buffer[pixelOffset + GBEMU_5] * secondWeight;
                pixelOffset += this.originalWidthMultipliedByChannels;
                finalOffset += this.targetWidthMultipliedByChannels;
            }
            targetPosition += GBEMU_3;
            weight += ratioWeight;
        }
        return outputBuffer;
    }
    resizeWidthInterpolatedRGBA(buffer) {
        let ratioWeight = (this.widthOriginal - 1) / this.targetWidth;
        let weight = 0;
        let finalOffset = 0;
        let pixelOffset = 0;
        let outputBuffer = this.widthBuffer;
        let targetPosition = 0;
        while (targetPosition < this.targetWidthMultipliedByChannels) {
            //Calculate weightings:
            let secondWeight = weight % 1;
            let firstWeight = 1 - secondWeight;
            //Interpolate:
            finalOffset = targetPosition;
            pixelOffset = Math.floor(weight) * GBEMU_4;
            while (finalOffset < this.widthPassResultSize) {
                outputBuffer[finalOffset] = buffer[pixelOffset] * firstWeight + buffer[pixelOffset + GBEMU_4] * secondWeight;
                outputBuffer[finalOffset + 1] = buffer[pixelOffset + 1] * firstWeight + buffer[pixelOffset + GBEMU_5] * secondWeight;
                outputBuffer[finalOffset + GBEMU_2] = buffer[pixelOffset + GBEMU_2] * firstWeight + buffer[pixelOffset + GBEMU_6] * secondWeight;
                outputBuffer[finalOffset + GBEMU_3] = buffer[pixelOffset + GBEMU_3] * firstWeight + buffer[pixelOffset + GBEMU_7] * secondWeight;
                pixelOffset += this.originalWidthMultipliedByChannels;
                finalOffset += this.targetWidthMultipliedByChannels;
            }
            targetPosition += GBEMU_4;
            weight += ratioWeight;
        }
        return outputBuffer;
    }
    resizeWidthRGBA(buffer) {
        let ratioWeight = this.ratioWeightWidthPass;
        let weight = 0;
        let amountToNext = 0;
        let actualPosition = 0;
        let currentPosition = 0;
        let line = 0;
        let pixelOffset = 0;
        let outputOffset = 0;
        let nextLineOffsetOriginalWidth = this.originalWidthMultipliedByChannels - GBEMU_3;
        let nextLineOffsetTargetWidth = this.targetWidthMultipliedByChannels - GBEMU_3;
        let output = this.outputWidthWorkBench;
        let outputBuffer = this.widthBuffer;
        do {
            line = 0;
            while (line < this.originalHeightMultipliedByChannels) {
                output[line++] = 0;
                output[line++] = 0;
                output[line++] = 0;
                output[line++] = 0;
            }
            weight = ratioWeight;
            do {
                amountToNext = 1 + actualPosition - currentPosition;
                if (weight >= amountToNext) {
                    line = 0;
                    pixelOffset = actualPosition;
                    while (line < this.originalHeightMultipliedByChannels) {
                        output[line++] += buffer[pixelOffset++] * amountToNext;
                        output[line++] += buffer[pixelOffset++] * amountToNext;
                        output[line++] += buffer[pixelOffset++] * amountToNext;
                        output[line++] += buffer[pixelOffset] * amountToNext;
                        pixelOffset += nextLineOffsetOriginalWidth;
                    }
                    actualPosition = actualPosition + GBEMU_4;
                    currentPosition = actualPosition;
                    weight -= amountToNext;
                }
                else {
                    line = 0;
                    pixelOffset = actualPosition;
                    while (line < this.originalHeightMultipliedByChannels) {
                        output[line++] += buffer[pixelOffset++] * weight;
                        output[line++] += buffer[pixelOffset++] * weight;
                        output[line++] += buffer[pixelOffset++] * weight;
                        output[line++] += buffer[pixelOffset] * weight;
                        pixelOffset += nextLineOffsetOriginalWidth;
                    }
                    currentPosition += weight;
                    break;
                }
            } while (weight > 0 && actualPosition < this.originalWidthMultipliedByChannels);
            line = 0;
            pixelOffset = outputOffset;
            while (line < this.originalHeightMultipliedByChannels) {
                outputBuffer[pixelOffset++] = output[line++] / ratioWeight;
                outputBuffer[pixelOffset++] = output[line++] / ratioWeight;
                outputBuffer[pixelOffset++] = output[line++] / ratioWeight;
                outputBuffer[pixelOffset] = output[line++] / ratioWeight;
                pixelOffset += nextLineOffsetTargetWidth;
            }
            outputOffset += GBEMU_4;
        } while (outputOffset < this.targetWidthMultipliedByChannels);
        return outputBuffer;
    }
    resizeHeightRGB(buffer) {
        let ratioWeight = this.ratioWeightHeightPass;
        let weight = 0;
        let amountToNext = 0;
        let actualPosition = 0;
        let currentPosition = 0;
        let pixelOffset = 0;
        let outputOffset = 0;
        let output = this.outputHeightWorkBench;
        let outputBuffer = this.heightBuffer;
        do {
            pixelOffset = 0;
            while (pixelOffset < this.targetWidthMultipliedByChannels) {
                output[pixelOffset++] = 0;
                output[pixelOffset++] = 0;
                output[pixelOffset++] = 0;
            }
            weight = ratioWeight;
            do {
                amountToNext = 1 + actualPosition - currentPosition;
                if (weight >= amountToNext) {
                    pixelOffset = 0;
                    while (pixelOffset < this.targetWidthMultipliedByChannels) {
                        output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
                        output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
                        output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
                    }
                    currentPosition = actualPosition;
                    weight -= amountToNext;
                }
                else {
                    pixelOffset = 0;
                    amountToNext = actualPosition;
                    while (pixelOffset < this.targetWidthMultipliedByChannels) {
                        output[pixelOffset++] += buffer[amountToNext++] * weight;
                        output[pixelOffset++] += buffer[amountToNext++] * weight;
                        output[pixelOffset++] += buffer[amountToNext++] * weight;
                    }
                    currentPosition += weight;
                    break;
                }
            } while (weight > 0 && actualPosition < this.widthPassResultSize);
            pixelOffset = 0;
            while (pixelOffset < this.targetWidthMultipliedByChannels) {
                outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
                outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
                outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
            }
        } while (outputOffset < this.finalResultSize);
        return outputBuffer;
    }
    resizeHeightInterpolated(buffer) {
        let ratioWeight = (this.heightOriginal - 1) / this.targetHeight;
        let weight = 0;
        let finalOffset = 0;
        let pixelOffset = 0;
        let pixelOffsetAccumulated = 0;
        let pixelOffsetAccumulated2 = 0;
        let outputBuffer = this.heightBuffer;
        do {
            //Calculate weightings:
            let secondWeight = weight % 1;
            let firstWeight = 1 - secondWeight;
            //Interpolate:
            pixelOffsetAccumulated = Math.floor(weight) * this.targetWidthMultipliedByChannels;
            pixelOffsetAccumulated2 = pixelOffsetAccumulated + this.targetWidthMultipliedByChannels;
            pixelOffset = 0;
            while (pixelOffset < this.targetWidthMultipliedByChannels) {
                outputBuffer[finalOffset++] =
                    buffer[pixelOffsetAccumulated + pixelOffset] * firstWeight + buffer[pixelOffsetAccumulated2 + pixelOffset] * secondWeight;
                pixelOffset += 1;
            }
            weight += ratioWeight;
        } while (finalOffset < this.finalResultSize);
        return outputBuffer;
    }
    resizeHeightRGBA(buffer) {
        let ratioWeight = this.ratioWeightHeightPass;
        let weight = 0;
        let amountToNext = 0;
        let actualPosition = 0;
        let currentPosition = 0;
        let pixelOffset = 0;
        let outputOffset = 0;
        let output = this.outputHeightWorkBench;
        let outputBuffer = this.heightBuffer;
        do {
            pixelOffset = 0;
            while (pixelOffset < this.targetWidthMultipliedByChannels) {
                output[pixelOffset++] = 0;
                output[pixelOffset++] = 0;
                output[pixelOffset++] = 0;
                output[pixelOffset++] = 0;
            }
            weight = ratioWeight;
            do {
                amountToNext = 1 + actualPosition - currentPosition;
                if (weight >= amountToNext) {
                    pixelOffset = 0;
                    while (pixelOffset < this.targetWidthMultipliedByChannels) {
                        output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
                        output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
                        output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
                        output[pixelOffset++] += buffer[actualPosition++] * amountToNext;
                    }
                    currentPosition = actualPosition;
                    weight -= amountToNext;
                }
                else {
                    pixelOffset = 0;
                    amountToNext = actualPosition;
                    while (pixelOffset < this.targetWidthMultipliedByChannels) {
                        output[pixelOffset++] += buffer[amountToNext++] * weight;
                        output[pixelOffset++] += buffer[amountToNext++] * weight;
                        output[pixelOffset++] += buffer[amountToNext++] * weight;
                        output[pixelOffset++] += buffer[amountToNext++] * weight;
                    }
                    currentPosition += weight;
                    break;
                }
            } while (weight > 0 && actualPosition < this.widthPassResultSize);
            pixelOffset = 0;
            while (pixelOffset < this.targetWidthMultipliedByChannels) {
                outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
                outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
                outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
                outputBuffer[outputOffset++] = Math.round(output[pixelOffset++] / ratioWeight);
            }
        } while (outputOffset < this.finalResultSize);
        return outputBuffer;
    }
    resize(buffer) {
        return this.resizeHeight(this.resizeWidth(buffer));
    }
    bypassResizer(buffer) {
        //Just return the buffer passsed:
        return buffer;
    }
    initializeFirstPassBuffers(biLINEARAlgo) {
        //Initialize the internal width pass buffers:
        this.widthBuffer = this.generateFloatBuffer(this.widthPassResultSize);
        if (!biLINEARAlgo) {
            this.outputWidthWorkBench = this.generateFloatBuffer(this.originalHeightMultipliedByChannels);
        }
    }
    initializeSecondPassBuffers(biLINEARAlgo) {
        //Initialize the internal height pass buffers:
        this.heightBuffer = this.generateUint8Buffer(this.finalResultSize);
        if (!biLINEARAlgo) {
            this.outputHeightWorkBench = this.generateFloatBuffer(this.targetWidthMultipliedByChannels);
        }
    }
    generateFloatBuffer(bufferLength) {
        //Generate a float32 typed array buffer:
        return new Float32Array(bufferLength);
    }
    generateUint8Buffer(bufferLength) {
        //Generate a uint8 typed array buffer:
        return new Uint8Array(bufferLength);
    }
}
// End of js/other/resize.js file.
// Remaining files are in gbemu-part2.js, since they run in strict mode.
// ------ gbemu-part2 ------
class GameBoyCore {
    constructor(canvas, romImage) {
        //Params, etc...
        this.canvas = null; //Canvas DOM object for drawing out the graphics to.
        this.drawContext = null; //LCD Context
        //CPU Registers and Flags:
        this.registerA = GBEMU_0x01; //Register A (Accumulator)
        this.fZero = true; //Register F  - Result was zero
        this.fSubtract = false; //Register F  - Subtraction was executed
        this.fHalfCarry = true; //Register F  - Half carry or half borrow
        this.fCarry = true; //Register F  - Carry or borrow
        this.registerB = GBEMU_0x00; //Register B
        this.registerC = GBEMU_0x13; //Register C
        this.registerD = GBEMU_0x00; //Register D
        this.registerE = GBEMU_0xD8; //Register E
        this.registerF = 0; //Register F
        this.registersHL = GBEMU_0x014D; //Registers H and L combined
        this.stackPointer = GBEMU_0xFFFE; //Stack Pointer
        this.programCounter = GBEMU_0x0100; //Program Counter
        //Some CPU Emulation State Variables:
        this.cpuCyclesTotal = 0; //Relative CPU clocking to speed set, rounded appropriately.
        this.cpuCyclesTotalBase = 0; //Relative CPU clocking to speed set base.
        this.cpuCyclesTotalCurrent = 0; //Relative CPU clocking to speed set, the directly used value.
        this.cpuCyclesTotalRoundoff = 0; //Clocking per iteration rounding catch.
        this.baseCPUCyclesPerIteration = 0; //CPU clocks per iteration at 1x speed.
        this.remainingClocks = 0; //HALT clocking overrun carry over.
        this.inBootstrap = true; //Whether we're in the GBC boot rom.
        this.usedBootrom = false; //Updated upon rom loading...
        this.usedGBCBootrom = false; //Did we boot to the GBC boot rom?
        this.halt = false; //Has the CPU been suspended until the next interrupt?
        this.skipPCIncrement = false; //Did we trip the DMG Halt bug?
        this.stopEmulator = GBEMU_3; //Has the emulation been paused or a frame has ended?
        this.ime = true; //Are interrupts enabled?
        this.irqLineMatched = 0; //CPU IRQ assertion.
        this.interruptsRequested = 0; //IF Register
        this.interruptsEnabled = 0; //IE Register
        this.hdmaRunning = false; //HDMA Transfer Flag - GBC only
        this.cpuTicks = 0; //The number of clock cycles emulated.
        this.doubleSpeedShifter = 0; //GBC double speed clocking shifter.
        this.joyPad = GBEMU_0xFF; //Joypad State (two four-bit states actually)
        this.cpuStopped = false; //CPU STOP status.
        //Main RAM, MBC RAM, GBC Main RAM, vram, etc.
        this.memoryReader = []; //Array of functions mapped to read back memory
        this.memoryWriter = []; //Array of functions mapped to write to memory
        this.memoryHighReader = []; //Array of functions mapped to read back 0xFFXX memory
        this.memoryHighWriter = []; //Array of functions mapped to write to 0xFFXX memory
        this.rom = new Int8Array(); //The full rom file dumped to an array.
        this.memory = new Int8Array(); //Main Core Memory
        this.mbcRam = new Int8Array(); //Switchable RAM (Used by games for more RAM) for the main memory range 0xA000 - 0xC000.
        this.vram = new Int8Array(); //Extra vram bank for GBC.
        this.gbcMemory = new Int8Array(); //GBC main RAM Banks
        this.mbc1Mode = false; //MBC1 Type (GBEMU_4/GBEMU_32, GBEMU_16/GBEMU_8)
        this.mbcRamBanksEnabled = false; //MBC RAM Access Control.
        this.currMBCRAMBank = 0; //MBC Currently Indexed RAM Bank
        this.currMBCRAMBankPosition = -GBEMU_0xA000; //MBC Position Adder;
        this.cGBC = false; //GameBoy Color detection.
        this.gbcRamBank = 1; //Currently Switched GameBoy Color ram bank
        this.gbcRamBankPosition = -GBEMU_0xD000; //GBC RAM offset from address start.
        this.gbcRamBankPositionECHO = -GBEMU_0xF000; //GBC RAM (ECHO mirroring) offset from address start.
        this.ramBanks = [0, 1, GBEMU_2, GBEMU_4, GBEMU_16]; //Used to map the RAM banks to maximum size the MBC used can do.
        this.romBank1offs = 0; //Offset of the rom bank switching.
        this.currentromBank = 0; //The parsed current rom bank selection.
        this.cartridgeType = 0; //Cartridge Type
        this.name = ''; //Name of the game
        this.gameCode = ''; //Game code (Suffix for older games)
        this.fromSaveState = false; //A boolean to see if this was loaded in as a save state.
        this.savedStateFileName = ''; //When loaded in as a save state, this will not be empty.
        this.statTracker = 0; //Tracker for STAT triggering.
        this.modeSTAT = 0; //The scan line mode (for lines 1-144 it's GBEMU_2-GBEMU_3-0, for 145-154 it's 1)
        this.spriteCount = GBEMU_252; //Mode GBEMU_3 extra clocking counter (Depends on how many sprites are on the current line.).
        this.lycMatchTriggerSTAT = false; //Should we trigger an interrupt if LY==LYC?
        this.mode2TriggerSTAT = false; //Should we trigger an interrupt if in mode GBEMU_2?
        this.mode1TriggerSTAT = false; //Should we trigger an interrupt if in mode 1?
        this.mode0TriggerSTAT = false; //Should we trigger an interrupt if in mode 0?
        this.lcdIsOn = false; //Is the emulated LCD controller on?
        this.lineControl = []; //Array of functions to handle each scan line we do (onscreen + offscreen)
        this.disPlayOffControl = [
            parentObj => {
                //Array of line 0 function to handle the LCD controller when it's off (Do nothing!).
            }
        ];
        this.lcdControl = []; //Pointer to either lineControl or disPlayOffControl.
        //RTC (Real Time Clock for MBC3):
        this.rtcIsLatched = false;
        this.latchedSeconds = 0; //RTC latched seconds.
        this.latchedMinutes = 0; //RTC latched minutes.
        this.latchedHours = 0; //RTC latched hours.
        this.latchedLDays = 0; //RTC latched lower GBEMU_8-bits of the day counter.
        this.latchedHDays = 0; //RTC latched high-bit of the day counter.
        this.rtcSeconds = 0; //RTC seconds counter.
        this.rtcMinutes = 0; //RTC minutes counter.
        this.rtcHours = 0; //RTC hours counter.
        this.rtcDays = 0; //RTC days counter.
        this.rtcDayOverFlow = false; //Did the RTC overflow and wrap the day counter?
        this.rtcHalt = false; //Is the RTC allowed to clock up?
        //Gyro:
        this.highX = GBEMU_127;
        this.lowX = GBEMU_127;
        this.highY = GBEMU_127;
        this.lowY = GBEMU_127;
        //Sound variables:
        this.audioHandle = null; //XAudioJS handle
        this.numSamplesTotal = 0; //Length of the sound buffers.
        this.sampleSize = 0; //Length of the sound buffer for one channel.
        this.dutyLookup = [
            //Map the duty values given to ones we can work with.
            [false, false, false, false, false, false, false, true], [true, false, false, false, false, false, false, true], [true, false, false, false, false, true, true, true], [false, true, true, true, true, true, true, false]
        ];
        this.currentBuffer = new Int8Array(); //The audio buffer we're working on.
        this.secondaryBuffer = new Int8Array();
        this.bufferContainAmount = 0; //Buffer maintenance metric.
        this.lsfr15Table = new Int8Array();
        this.lsfr7Table = new Int8Array();
        this.noiseSampleTable = new Int8Array();
        this.soundMasterEnabled = false; //As its name implies
        this.channel3PCM = new Int8Array(); //Channel GBEMU_3 adjusted sample buffer.
        //Vin Shit:
        this.vinLeftChannelMasterVolume = GBEMU_8; //Computed post-mixing volume.
        this.vinRightChannelMasterVolume = GBEMU_8; //Computed post-mixing volume.
        //Channel paths enabled:
        this.leftChannel1 = false;
        this.leftChannel2 = false;
        this.leftChannel3 = false;
        this.leftChannel4 = false;
        this.rightChannel1 = false;
        this.rightChannel2 = false;
        this.rightChannel3 = false;
        this.rightChannel4 = false;
        //Channel output level caches:
        this.channel1currentSampleLeft = 0;
        this.channel1currentSampleRight = 0;
        this.channel2currentSampleLeft = 0;
        this.channel2currentSampleRight = 0;
        this.channel3currentSampleLeft = 0;
        this.channel3currentSampleRight = 0;
        this.channel4currentSampleLeft = 0;
        this.channel4currentSampleRight = 0;
        this.channel1currentSampleLeftSecondary = 0;
        this.channel1currentSampleRightSecondary = 0;
        this.channel2currentSampleLeftSecondary = 0;
        this.channel2currentSampleRightSecondary = 0;
        this.channel3currentSampleLeftSecondary = 0;
        this.channel3currentSampleRightSecondary = 0;
        this.channel4currentSampleLeftSecondary = 0;
        this.channel4currentSampleRightSecondary = 0;
        this.channel1currentSampleLeftTrimary = 0;
        this.channel1currentSampleRightTrimary = 0;
        this.channel2currentSampleLeftTrimary = 0;
        this.channel2currentSampleRightTrimary = 0;
        this.mixerOutputCache = 0;
        //Pre-multipliers to cache some calculations:
        this.machineOut = 0; //Premultiplier for audio samples per instruction.
        //Audio generation counters:
        this.audioTicks = 0; //Used to sample the audio system every x CPU instructions.
        this.audioIndex = 0; //Used to keep alignment on audio generation.
        this.rollover = 0; //Used to keep alignment on the number of samples to output (Realign from counter alias).
        //Timing Variables
        this.emulatorTicks = 0; //Times for how many instructions to execute before ending the loop.
        this.divTicks = GBEMU_56; //DIV Ticks Counter (Invisible lower GBEMU_8-bit)
        this.lcdTicks = GBEMU_60; //Counter for how many instructions have been executed on a scanline so far.
        this.timerTicks = 0; //Counter for the TIMA timer.
        this.timaEnabled = false; //Is TIMA enabled?
        this.tacClocker = GBEMU_1024; //Timer Max Ticks
        this.serialTimer = 0; //Serial IRQ Timer
        this.serialShiftTimer = 0; //Serial Transfer Shift Timer
        this.serialShiftTimerAllocated = 0; //Serial Transfer Shift Timer Refill
        this.irqEnableDelay = 0; //Are the interrupts on queue to be enabled?
        this.lastIteration = new NewDate().getTime(); //The last time we iterated the main loop.
        this.firstIteration = new NewDate().getTime(); //The line is changed for benchmarking.
        this.iterations = 0;
        this.actualScanLine = 0; //Actual scan line...
        this.lastUnrenderedLine = 0; //Last rendered scan line...
        this.queuedScanLines = 0;
        this.totalLinesPassed = 0;
        this.haltPostClocks = 0; //Post-Halt clocking.
        //rom Cartridge Components:
        this.cMBC1 = false; //Does the cartridge use MBC1?
        this.cMBC2 = false; //Does the cartridge use MBC2?
        this.cMBC3 = false; //Does the cartridge use MBC3?
        this.cMBC5 = false; //Does the cartridge use MBC5?
        this.cMBC7 = false; //Does the cartridge use MBC7?
        this.cSRAM = false; //Does the cartridge use save RAM?
        this.cMMMO1 = false; //...
        this.cRUMBLE = false; //Does the cartridge use the RUMBLE addressing (modified MBC5)?
        this.cCamera = false; //Is the cartridge actually a GameBoy Camera?
        this.cTAMA5 = false; //Does the cartridge use TAMA5? (Tamagotchi Cartridge)
        this.cHuC3 = false; //Does the cartridge use HuC3 (Hudson Soft / modified MBC3)?
        this.cHuC1 = false; //Does the cartridge use HuC1 (Hudson Soft / modified MBC1)?
        this.cTimeR = false; //Does the cartridge have an RTC?
        this.romBanks = new Map([
            //1 Bank = GBEMU_16 KBytes = 256 Kbits
            [0, GBEMU_2], [1, GBEMU_4], [GBEMU_2, GBEMU_8], [GBEMU_3, GBEMU_16], [GBEMU_4, GBEMU_32], [GBEMU_5, GBEMU_64], [GBEMU_6, GBEMU_128], [GBEMU_7, GBEMU_256], [GBEMU_8, GBEMU_512], [GBEMU_0x52, GBEMU_72], [GBEMU_0x53, GBEMU_80], [GBEMU_0x54, GBEMU_96]
        ]);
        this.numRamBanks = 0; //How many RAM banks were actually allocated?
        //Graphics Variables
        this.currvramBank = 0; //Current vram bank for GBC.
        this.backgroundX = 0; //Register SCX (X-Scroll)
        this.backgroundY = 0; //Register SCY (Y-Scroll)
        this.gfxWindowDisplay = false; //Is the windows enabled?
        this.gfxSpriteShow = false; //Are sprites enabled?
        this.gfxSpriteNormalHeight = true; //Are we doing 8x8 or 8x16 sprites?
        this.bgEnabled = true; //Is the BG enabled?
        this.bgPriorityEnabled = true; //Can we flag the BG for priority over sprites?
        this.gfxWindowCHRBankPosition = 0; //The current bank of the character map the window uses.
        this.gfxBackgroundCHRBankPosition = 0; //The current bank of the character map the BG uses.
        this.gfxBackgroundBankOffset = GBEMU_0x80; //Fast mapping of the tile numbering/
        this.windowY = 0; //Current Y offset of the window.
        this.windowX = 0; //Current X offset of the window.
        this.drewBlank = 0; //To prevent the repeating of drawing a blank screen.
        this.drewFrame = false; //Throttle how many draws we can do to once per iteration.
        this.midScanlineOffset = -1; //mid-scanline rendering offset.
        this.pixelEnd = 0; //track the x-coord limit for line rendering (mid-scanline usage).
        this.currentX = 0; //The x-coord we left off at for mid-scanline rendering.
        //BG Tile Pointer Caches:
        this.bgCHRBank1 = new ArrayObject();
        this.bgCHRBank2 = new ArrayObject();
        this.bgCHRCurrentBank = null;
        //Tile Data Cache:
        this.tileCache = [];
        //Palettes:
        this.colors = [GBEMU_0xEFFFDE, GBEMU_0xADD794, GBEMU_0x529273, GBEMU_0x183442]; //'Classic' GameBoy palette colors.
        this.objPalette = new Int32Array();
        this.bgPalette = new Int32Array();
        this.gbcOBJRawPalette = new Int32Array();
        this.gbcBGRawPalette = new Int32Array();
        this.gbOBJPalette = new Int32Array();
        this.gbBGPalette = new Int32Array();
        this.gbcOBJPalette = new Int32Array();
        this.gbcBGPalette = new Int32Array();
        this.gbBGColorizedPalette = new Int32Array();
        this.gbOBJColorizedPalette = new Int32Array();
        this.cachedBGPaletteConversion = new Int32Array();
        this.cachedOBJPaletteConversion = new Int32Array();
        this.updateGBBGPalette = null;
        this.updateGBOBJPalette = null;
        this.colorizedGBPalettes = false;
        this.bgLayerRender = null; //Reference to the BG rendering function.
        this.windowLayerRender = null; //Reference to the window rendering function.
        this.spriteLayerRender = null; //Reference to the OAM rendering function.
        this.frameBuffer = new Int8Array(); //The internal frame-buffer.
        this.swizzledFrame = new Int8Array(); //The secondary gfx buffer that holds the converted RGBA values.
        this.canvasBuffer = null; //imageData handle
        this.pixelStart = 0; //Temp variable for holding the current working framebuffer offset.
        //Variables used for scaling in JS:
        this.onscreenWidth = GBEMU_160;
        this.offscreenWidth = GBEMU_160;
        this.onscreenHeight = GBEMU_144;
        this.offscreenHeight = GBEMU_144;
        this.offscreenRGBCount = this.onscreenWidth * this.onscreenHeight * GBEMU_4;
        // Start of code changed for benchmarking (removed rom):
        this.gbBOOTrom = [];
        this.gbCBOOTrom = [];
        // End of code changed for benchmarking.
        this.ffxxDump = [
            //Dump of the post-BOOT I/O register state (From gambatte):
            GBEMU_0x0F, GBEMU_0x00, GBEMU_0x7C, GBEMU_0xFF, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0xF8, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0x01, GBEMU_0x80, GBEMU_0xBF, GBEMU_0xF3, GBEMU_0xFF, GBEMU_0xBF, GBEMU_0xFF, GBEMU_0x3F, GBEMU_0x00, GBEMU_0xFF, GBEMU_0xBF, GBEMU_0x7F, GBEMU_0xFF, GBEMU_0x9F, GBEMU_0xFF, GBEMU_0xBF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0x00, GBEMU_0x00, GBEMU_0xBF, GBEMU_0x77, GBEMU_0xF3, GBEMU_0xF1, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x91, GBEMU_0x80, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0xFC, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0xFF, GBEMU_0x7E, GBEMU_0xFF, GBEMU_0xFE, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0x3E, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xC0, GBEMU_0xFF, GBEMU_0xC1, GBEMU_0x00, GBEMU_0xFE, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xF8, GBEMU_0xFF, GBEMU_0x00, GBEMU_0x00, GBEMU_0x00, GBEMU_0x8F, GBEMU_0x00, GBEMU_0x00, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xFF, GBEMU_0xCE, GBEMU_0xED, GBEMU_0x66, GBEMU_0x66, GBEMU_0xCC, GBEMU_0x0D, GBEMU_0x00, GBEMU_0x0B, GBEMU_0x03, GBEMU_0x73, GBEMU_0x00, GBEMU_0x83, GBEMU_0x00, GBEMU_0x0C, GBEMU_0x00, GBEMU_0x0D, GBEMU_0x00, GBEMU_0x08, GBEMU_0x11, GBEMU_0x1F, GBEMU_0x88, GBEMU_0x89, GBEMU_0x00, GBEMU_0x0E, GBEMU_0xDC, GBEMU_0xCC, GBEMU_0x6E, GBEMU_0xE6, GBEMU_0xDD, GBEMU_0xDD, GBEMU_0xD9, GBEMU_0x99, GBEMU_0xBB, GBEMU_0xBB, GBEMU_0x67, GBEMU_0x63, GBEMU_0x6E, GBEMU_0x0E, GBEMU_0xEC, GBEMU_0xCC, GBEMU_0xDD, GBEMU_0xDC, GBEMU_0x99, GBEMU_0x9F, GBEMU_0xBB, GBEMU_0xB9, GBEMU_0x33, GBEMU_0x3E, GBEMU_0x45, GBEMU_0xEC, GBEMU_0x52, GBEMU_0xFA, GBEMU_0x08, GBEMU_0xB7, GBEMU_0x07, GBEMU_0x5D, GBEMU_0x01, GBEMU_0xFD, GBEMU_0xC0, GBEMU_0xFF, GBEMU_0x08, GBEMU_0xFC, GBEMU_0x00, GBEMU_0xE5, GBEMU_0x0B, GBEMU_0xF8, GBEMU_0xC2, GBEMU_0xCE, GBEMU_0xF4, GBEMU_0xF9, GBEMU_0x0F, GBEMU_0x7F, GBEMU_0x45, GBEMU_0x6D, GBEMU_0x3D, GBEMU_0xFE, GBEMU_0x46, GBEMU_0x97, GBEMU_0x33, GBEMU_0x5E, GBEMU_0x08, GBEMU_0xEF, GBEMU_0xF1, GBEMU_0xFF, GBEMU_0x86, GBEMU_0x83, GBEMU_0x24, GBEMU_0x74, GBEMU_0x12, GBEMU_0xFC, GBEMU_0x00, GBEMU_0x9F, GBEMU_0xB4, GBEMU_0xB7, GBEMU_0x06, GBEMU_0xD5, GBEMU_0xD0, GBEMU_0x7A, GBEMU_0x00, GBEMU_0x9E, GBEMU_0x04, GBEMU_0x5F, GBEMU_0x41, GBEMU_0x2F, GBEMU_0x1D, GBEMU_0x77, GBEMU_0x36, GBEMU_0x75, GBEMU_0x81, GBEMU_0xAA, GBEMU_0x70, GBEMU_0x3A, GBEMU_0x98, GBEMU_0xD1, GBEMU_0x71, GBEMU_0x02, GBEMU_0x4D, GBEMU_0x01, GBEMU_0xC1, GBEMU_0xFF, GBEMU_0x0D, GBEMU_0x00, GBEMU_0xD3, GBEMU_0x05, GBEMU_0xF9, GBEMU_0x00, GBEMU_0x0B, GBEMU_0x00
        ];
        // other perpty
        this.channel1FrequencyTracker = GBEMU_0x2000;
        this.channel1DutyTracker = 0;
        this.channel1CachedDuty = [];
        this.channel1totalLength = 0;
        this.channel1envelopeVolume = 0;
        this.channel1envelopeType = false;
        this.channel1envelopeSweeps = 0;
        this.channel1envelopeSweepsLast = 0;
        this.channel1consecutive = true;
        this.channel1frequency = GBEMU_1985;
        this.channel1SweepFault = true;
        this.channel1ShadowFrequency = GBEMU_1985;
        this.channel1timeSweep = 1;
        this.channel1lastTimeSweep = 0;
        this.channel1numSweep = 0;
        this.channel1frequencySweepDivider = 0;
        this.channel1decreaseSweep = false;
        this.channel2FrequencyTracker = GBEMU_0x2000;
        this.channel2DutyTracker = 0;
        this.channel2CachedDuty = [];
        this.channel2totalLength = 0;
        this.channel2envelopeVolume = 0;
        this.channel2envelopeType = false;
        this.channel2envelopeSweeps = 0;
        this.channel2envelopeSweepsLast = 0;
        this.channel2consecutive = true;
        this.channel2frequency = 0;
        this.channel3canPlay = false;
        this.channel3totalLength = 0;
        this.channel3patternType = GBEMU_4;
        this.channel3frequency = 0;
        this.channel3consecutive = true;
        this.channel3Counter = GBEMU_0x418;
        this.channel4FrequencyPeriod = GBEMU_8;
        this.channel4totalLength = 0;
        this.channel4envelopeVolume = 0;
        this.channel4currentVolume = 0;
        this.channel4envelopeType = false;
        this.channel4envelopeSweeps = 0;
        this.channel4envelopeSweepsLast = 0;
        this.channel4consecutive = true;
        this.channel4BitRange = GBEMU_0x7FFF;
        this.channel4VolumeShifter = GBEMU_15;
        this.channel1FrequencyCounter = GBEMU_0x200;
        this.channel2FrequencyCounter = GBEMU_0x200;
        this.channel3FrequencyPeriod = GBEMU_0x800;
        this.channel3lastSampleLookup = 0;
        this.channel4lastSampleLookup = 0;
        this.sequencerClocks = GBEMU_0x2000;
        this.sequencePosition = 0;
        this.channel4Counter = GBEMU_8;
        this.cachedChannel3Sample = 0;
        this.cachedChannel4Sample = 0;
        this.channel1Enabled = false;
        this.channel2Enabled = false;
        this.channel3Enabled = false;
        this.channel4Enabled = false;
        this.channel1canPlay = false;
        this.channel2canPlay = false;
        this.channel4canPlay = false;
        this.romBankEdge = 0;
        this.cBATT = false;
        this.oamAddressCache = new Int32Array(GBEMU_10);
        this.sortBuffer = new Int8Array(GBEMU_0x100);
        this.resizer = null;
        this.instructions = 0;
        this.totalInstructions = 0;
        this.drawContextOnscreen = null;
        this.drawContextOffscreen = null;
        this.canvasOffscreen = null;
        this.openMBC = (name) => [];
        this.openRTC = (filename) => [];
        this.numRomBanks = 0;
        this.opCode = [
            //NOP
            //#0x00:
            parentObj => {
                //Do Nothing...
            },
            //LD BC, nn
            //#0x01:
            parentObj => {
                parentObj.registerC = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.registerB = parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF);
                parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
            },
            //LD (BC), A
            //#0x02:
            parentObj => {
                parentObj.memoryWrite((parentObj.registerB << GBEMU_8) | parentObj.registerC, parentObj.registerA);
            },
            //INC BC
            //#0x03:
            parentObj => {
                let tempVar = ((parentObj.registerB << GBEMU_8) | parentObj.registerC) + 1;
                parentObj.registerB = (tempVar >> GBEMU_8) & GBEMU_0xFF;
                parentObj.registerC = tempVar & GBEMU_0xFF;
            },
            //INC B
            //#0x04:
            parentObj => {
                parentObj.registerB = (parentObj.registerB + 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerB === 0;
                parentObj.fHalfCarry = (parentObj.registerB & GBEMU_0xF) === 0;
                parentObj.fSubtract = false;
            },
            //DEC B
            //#0x05:
            parentObj => {
                parentObj.registerB = (parentObj.registerB - 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerB === 0;
                parentObj.fHalfCarry = (parentObj.registerB & GBEMU_0xF) === GBEMU_0xF;
                parentObj.fSubtract = true;
            },
            //LD B, n
            //#0x06:
            parentObj => {
                parentObj.registerB = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
            },
            //RLCA
            //#0x07:
            parentObj => {
                parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
                parentObj.registerA = ((parentObj.registerA << 1) & GBEMU_0xFF) | (parentObj.registerA >> GBEMU_7);
                parentObj.fZero = false;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
            },
            //LD (nn), SP
            //#0x08:
            parentObj => {
                let tempVar = (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                    parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                parentObj.memoryWrite(tempVar, parentObj.stackPointer & GBEMU_0xFF);
                parentObj.memoryWrite((tempVar + 1) & GBEMU_0xFFFF, parentObj.stackPointer >> GBEMU_8);
            },
            //ADD HL, BC
            //#0x09:
            parentObj => {
                let dirtySum = parentObj.registersHL + ((parentObj.registerB << GBEMU_8) | parentObj.registerC);
                parentObj.fHalfCarry = (parentObj.registersHL & GBEMU_0xFFF) > (dirtySum & GBEMU_0xFFF);
                parentObj.fCarry = dirtySum > GBEMU_0xFFFF;
                parentObj.registersHL = dirtySum & GBEMU_0xFFFF;
                parentObj.fSubtract = false;
            },
            //LD A, (BC)
            //#0x0A:
            parentObj => {
                parentObj.registerA = parentObj.memoryRead((parentObj.registerB << GBEMU_8) | parentObj.registerC);
            },
            //DEC BC
            //#0x0B:
            parentObj => {
                let tempVar = (((parentObj.registerB << GBEMU_8) | parentObj.registerC) - 1) & GBEMU_0xFFFF;
                parentObj.registerB = tempVar >> GBEMU_8;
                parentObj.registerC = tempVar & GBEMU_0xFF;
            },
            //INC C
            //#0x0C:
            parentObj => {
                parentObj.registerC = (parentObj.registerC + 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerC === 0;
                parentObj.fHalfCarry = (parentObj.registerC & GBEMU_0xF) === 0;
                parentObj.fSubtract = false;
            },
            //DEC C
            //#0x0D:
            parentObj => {
                parentObj.registerC = (parentObj.registerC - 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerC === 0;
                parentObj.fHalfCarry = (parentObj.registerC & GBEMU_0xF) === GBEMU_0xF;
                parentObj.fSubtract = true;
            },
            //LD C, n
            //#0x0E:
            parentObj => {
                parentObj.registerC = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
            },
            //RRCA
            //#0x0F:
            parentObj => {
                parentObj.registerA = (parentObj.registerA >> 1) | ((parentObj.registerA & 1) << GBEMU_7);
                parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
                parentObj.fZero = false;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
            },
            //STOP
            //#0x10:
            parentObj => {
                if (parentObj.cGBC) {
                    if ((parentObj.memory[GBEMU_0xFF4D] & GBEMU_0x01) === GBEMU_0x01) {
                        //Speed change requested.
                        if (parentObj.memory[GBEMU_0xFF4D] > GBEMU_0x7F) {
                            //Go back to single speed mode.
                            cout('Going into single clock speed mode.', 0);
                            parentObj.doubleSpeedShifter = 0;
                            parentObj.memory[GBEMU_0xFF4D] &= GBEMU_0x7F; //Clear the double speed mode flag.
                        }
                        else {
                            //Go to double speed mode.
                            cout('Going into double clock speed mode.', 0);
                            parentObj.doubleSpeedShifter = 1;
                            parentObj.memory[GBEMU_0xFF4D] |= GBEMU_0x80; //Set the double speed mode flag.
                        }
                        parentObj.memory[GBEMU_0xFF4D] &= GBEMU_0xFE; //Reset the request bit.
                    }
                    else {
                        parentObj.handleSTOP(); //Handle Stop
                    }
                }
                else {
                    parentObj.handleSTOP();
                }
            },
            //LD DE, nn
            //#0x11:
            parentObj => {
                parentObj.registerE = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.registerD = parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF);
                parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
            },
            //LD (DE), A
            //#0x12:
            parentObj => {
                parentObj.memoryWrite((parentObj.registerD << GBEMU_8) | parentObj.registerE, parentObj.registerA);
            },
            //INC DE
            //#0x13:
            parentObj => {
                let tempVar = ((parentObj.registerD << GBEMU_8) | parentObj.registerE) + 1;
                parentObj.registerD = (tempVar >> GBEMU_8) & GBEMU_0xFF;
                parentObj.registerE = tempVar & GBEMU_0xFF;
            },
            //INC D
            //#0x14:
            parentObj => {
                parentObj.registerD = (parentObj.registerD + 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerD === 0;
                parentObj.fHalfCarry = (parentObj.registerD & GBEMU_0xF) === 0;
                parentObj.fSubtract = false;
            },
            //DEC D
            //#0x15:
            parentObj => {
                parentObj.registerD = (parentObj.registerD - 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerD === 0;
                parentObj.fHalfCarry = (parentObj.registerD & GBEMU_0xF) === GBEMU_0xF;
                parentObj.fSubtract = true;
            },
            //LD D, n
            //#0x16:
            parentObj => {
                parentObj.registerD = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
            },
            //RLA
            //#0x17:
            parentObj => {
                let carry_flag = parentObj.fCarry ? 1 : 0;
                parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
                parentObj.registerA = ((parentObj.registerA << 1) & GBEMU_0xFF) | carry_flag;
                parentObj.fZero = false;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
            },
            //JR n
            //#0x18:
            parentObj => {
                parentObj.programCounter =
                    (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24) + 1) &
                        GBEMU_0xFFFF;
            },
            //ADD HL, DE
            //#0x19:
            parentObj => {
                let dirtySum = parentObj.registersHL + ((parentObj.registerD << GBEMU_8) | parentObj.registerE);
                parentObj.fHalfCarry = (parentObj.registersHL & GBEMU_0xFFF) > (dirtySum & GBEMU_0xFFF);
                parentObj.fCarry = dirtySum > GBEMU_0xFFFF;
                parentObj.registersHL = dirtySum & GBEMU_0xFFFF;
                parentObj.fSubtract = false;
            },
            //LD A, (DE)
            //#0x1A:
            parentObj => {
                parentObj.registerA = parentObj.memoryRead((parentObj.registerD << GBEMU_8) | parentObj.registerE);
            },
            //DEC DE
            //#0x1B:
            parentObj => {
                let tempVar = (((parentObj.registerD << GBEMU_8) | parentObj.registerE) - 1) & GBEMU_0xFFFF;
                parentObj.registerD = tempVar >> GBEMU_8;
                parentObj.registerE = tempVar & GBEMU_0xFF;
            },
            //INC E
            //#0x1C:
            parentObj => {
                parentObj.registerE = (parentObj.registerE + 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerE === 0;
                parentObj.fHalfCarry = (parentObj.registerE & GBEMU_0xF) === 0;
                parentObj.fSubtract = false;
            },
            //DEC E
            //#0x1D:
            parentObj => {
                parentObj.registerE = (parentObj.registerE - 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerE === 0;
                parentObj.fHalfCarry = (parentObj.registerE & GBEMU_0xF) === GBEMU_0xF;
                parentObj.fSubtract = true;
            },
            //LD E, n
            //#0x1E:
            parentObj => {
                parentObj.registerE = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
            },
            //RRA
            //#0x1F:
            parentObj => {
                let carry_flag = parentObj.fCarry ? GBEMU_0x80 : 0;
                parentObj.fCarry = (parentObj.registerA & 1) === 1;
                parentObj.registerA = (parentObj.registerA >> 1) | carry_flag;
                parentObj.fZero = false;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
            },
            //JR NZ, n
            //#0x20:
            parentObj => {
                if (!parentObj.fZero) {
                    parentObj.programCounter =
                        (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24) + 1) &
                            GBEMU_0xFFFF;
                    parentObj.cpuTicks += GBEMU_4;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                }
            },
            //LD HL, nn
            //#0x21:
            parentObj => {
                parentObj.registersHL =
                    (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
            },
            //LDI (HL), A
            //#0x22:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerA);
                parentObj.registersHL = (parentObj.registersHL + 1) & GBEMU_0xFFFF;
            },
            //INC HL
            //#0x23:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL + 1) & GBEMU_0xFFFF;
            },
            //INC H
            //#0x24:
            parentObj => {
                let h = ((parentObj.registersHL >> GBEMU_8) + 1) & GBEMU_0xFF;
                parentObj.fZero = h === 0;
                parentObj.fHalfCarry = (h & GBEMU_0xF) === 0;
                parentObj.fSubtract = false;
                parentObj.registersHL = (h << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
            },
            //DEC H
            //#0x25:
            parentObj => {
                let h = ((parentObj.registersHL >> GBEMU_8) - 1) & GBEMU_0xFF;
                parentObj.fZero = h === 0;
                parentObj.fHalfCarry = (h & GBEMU_0xF) === GBEMU_0xF;
                parentObj.fSubtract = true;
                parentObj.registersHL = (h << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
            },
            //LD H, n
            //#0x26:
            parentObj => {
                parentObj.registersHL =
                    (parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
            },
            //DAA
            //#0x27:
            parentObj => {
                if (!parentObj.fSubtract) {
                    if (parentObj.fCarry || parentObj.registerA > GBEMU_0x99) {
                        parentObj.registerA = (parentObj.registerA + GBEMU_0x60) & GBEMU_0xFF;
                        parentObj.fCarry = true;
                    }
                    if (parentObj.fHalfCarry || (parentObj.registerA & GBEMU_0xF) > GBEMU_0x9) {
                        parentObj.registerA = (parentObj.registerA + GBEMU_0x06) & GBEMU_0xFF;
                        parentObj.fHalfCarry = false;
                    }
                }
                else if (parentObj.fCarry && parentObj.fHalfCarry) {
                    parentObj.registerA = (parentObj.registerA + GBEMU_0x9A) & GBEMU_0xFF;
                    parentObj.fHalfCarry = false;
                }
                else if (parentObj.fCarry) {
                    parentObj.registerA = (parentObj.registerA + GBEMU_0xA0) & GBEMU_0xFF;
                }
                else if (parentObj.fHalfCarry) {
                    parentObj.registerA = (parentObj.registerA + GBEMU_0xFA) & GBEMU_0xFF;
                    parentObj.fHalfCarry = false;
                }
                parentObj.fZero = parentObj.registerA === 0;
            },
            //JR Z, n
            //#0x28:
            parentObj => {
                if (parentObj.fZero) {
                    parentObj.programCounter =
                        (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24) + 1) &
                            GBEMU_0xFFFF;
                    parentObj.cpuTicks += GBEMU_4;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                }
            },
            //ADD HL, HL
            //#0x29:
            parentObj => {
                parentObj.fHalfCarry = (parentObj.registersHL & GBEMU_0xFFF) > GBEMU_0x7FF;
                parentObj.fCarry = parentObj.registersHL > GBEMU_0x7FFF;
                parentObj.registersHL = (parentObj.registersHL << 1) & GBEMU_0xFFFF;
                parentObj.fSubtract = false;
            },
            //LDI A, (HL)
            //#0x2A:
            parentObj => {
                parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.registersHL = (parentObj.registersHL + 1) & GBEMU_0xFFFF;
            },
            //DEC HL
            //#0x2B:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL - 1) & GBEMU_0xFFFF;
            },
            //INC L
            //#0x2C:
            parentObj => {
                let L = (parentObj.registersHL + 1) & GBEMU_0xFF;
                parentObj.fZero = L === 0;
                parentObj.fHalfCarry = (L & GBEMU_0xF) === 0;
                parentObj.fSubtract = false;
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | L;
            },
            //DEC L
            //#0x2D:
            parentObj => {
                let L = (parentObj.registersHL - 1) & GBEMU_0xFF;
                parentObj.fZero = L === 0;
                parentObj.fHalfCarry = (L & GBEMU_0xF) === GBEMU_0xF;
                parentObj.fSubtract = true;
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | L;
            },
            //LD L, n
            //#0x2E:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
            },
            //CPL
            //#0x2F:
            parentObj => {
                parentObj.registerA ^= GBEMU_0xFF;
                parentObj.fSubtract = true;
                parentObj.fHalfCarry = true;
            },
            //JR NC, n
            //#0x30:
            parentObj => {
                if (!parentObj.fCarry) {
                    parentObj.programCounter =
                        (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24) + 1) &
                            GBEMU_0xFFFF;
                    parentObj.cpuTicks += GBEMU_4;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                }
            },
            //LD SP, nn
            //#0x31:
            parentObj => {
                parentObj.stackPointer =
                    (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
            },
            //LDD (HL), A
            //#0x32:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerA);
                parentObj.registersHL = (parentObj.registersHL - 1) & GBEMU_0xFFFF;
            },
            //INC SP
            //#0x33:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer + 1) & GBEMU_0xFFFF;
            },
            //INC (HL)
            //#0x34:
            parentObj => {
                let tempVar = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) + 1) & GBEMU_0xFF;
                parentObj.fZero = tempVar === 0;
                parentObj.fHalfCarry = (tempVar & GBEMU_0xF) === 0;
                parentObj.fSubtract = false;
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
            },
            //DEC (HL)
            //#0x35:
            parentObj => {
                let tempVar = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) - 1) & GBEMU_0xFF;
                parentObj.fZero = tempVar === 0;
                parentObj.fHalfCarry = (tempVar & GBEMU_0xF) === GBEMU_0xF;
                parentObj.fSubtract = true;
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
            },
            //LD (HL), n
            //#0x36:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
            },
            //SCF
            //#0x37:
            parentObj => {
                parentObj.fCarry = true;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
            },
            //JR C, n
            //#0x38:
            parentObj => {
                if (parentObj.fCarry) {
                    parentObj.programCounter =
                        (parentObj.programCounter + ((parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24) + 1) &
                            GBEMU_0xFFFF;
                    parentObj.cpuTicks += GBEMU_4;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                }
            },
            //ADD HL, SP
            //#0x39:
            parentObj => {
                let dirtySum = parentObj.registersHL + parentObj.stackPointer;
                parentObj.fHalfCarry = (parentObj.registersHL & GBEMU_0xFFF) > (dirtySum & GBEMU_0xFFF);
                parentObj.fCarry = dirtySum > GBEMU_0xFFFF;
                parentObj.registersHL = dirtySum & GBEMU_0xFFFF;
                parentObj.fSubtract = false;
            },
            //LDD A, (HL)
            //#0x3A:
            parentObj => {
                parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.registersHL = (parentObj.registersHL - 1) & GBEMU_0xFFFF;
            },
            //DEC SP
            //#0x3B:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
            },
            //INC A
            //#0x3C:
            parentObj => {
                parentObj.registerA = (parentObj.registerA + 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) === 0;
                parentObj.fSubtract = false;
            },
            //DEC A
            //#0x3D:
            parentObj => {
                parentObj.registerA = (parentObj.registerA - 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) === GBEMU_0xF;
                parentObj.fSubtract = true;
            },
            //LD A, n
            //#0x3E:
            parentObj => {
                parentObj.registerA = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
            },
            //CCF
            //#0x3F:
            parentObj => {
                parentObj.fCarry = !parentObj.fCarry;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
            },
            //LD B, B
            //#0x40:
            parentObj => {
                //Do nothing...
            },
            //LD B, C
            //#0x41:
            parentObj => {
                parentObj.registerB = parentObj.registerC;
            },
            //LD B, D
            //#0x42:
            parentObj => {
                parentObj.registerB = parentObj.registerD;
            },
            //LD B, E
            //#0x43:
            parentObj => {
                parentObj.registerB = parentObj.registerE;
            },
            //LD B, H
            //#0x44:
            parentObj => {
                parentObj.registerB = parentObj.registersHL >> GBEMU_8;
            },
            //LD B, L
            //#0x45:
            parentObj => {
                parentObj.registerB = parentObj.registersHL & GBEMU_0xFF;
            },
            //LD B, (HL)
            //#0x46:
            parentObj => {
                parentObj.registerB = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
            },
            //LD B, A
            //#0x47:
            parentObj => {
                parentObj.registerB = parentObj.registerA;
            },
            //LD C, B
            //#0x48:
            parentObj => {
                parentObj.registerC = parentObj.registerB;
            },
            //LD C, C
            //#0x49:
            parentObj => {
                //Do nothing...
            },
            //LD C, D
            //#0x4A:
            parentObj => {
                parentObj.registerC = parentObj.registerD;
            },
            //LD C, E
            //#0x4B:
            parentObj => {
                parentObj.registerC = parentObj.registerE;
            },
            //LD C, H
            //#0x4C:
            parentObj => {
                parentObj.registerC = parentObj.registersHL >> GBEMU_8;
            },
            //LD C, L
            //#0x4D:
            parentObj => {
                parentObj.registerC = parentObj.registersHL & GBEMU_0xFF;
            },
            //LD C, (HL)
            //#0x4E:
            parentObj => {
                parentObj.registerC = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
            },
            //LD C, A
            //#0x4F:
            parentObj => {
                parentObj.registerC = parentObj.registerA;
            },
            //LD D, B
            //#0x50:
            parentObj => {
                parentObj.registerD = parentObj.registerB;
            },
            //LD D, C
            //#0x51:
            parentObj => {
                parentObj.registerD = parentObj.registerC;
            },
            //LD D, D
            //#0x52:
            parentObj => {
                //Do nothing...
            },
            //LD D, E
            //#0x53:
            parentObj => {
                parentObj.registerD = parentObj.registerE;
            },
            //LD D, H
            //#0x54:
            parentObj => {
                parentObj.registerD = parentObj.registersHL >> GBEMU_8;
            },
            //LD D, L
            //#0x55:
            parentObj => {
                parentObj.registerD = parentObj.registersHL & GBEMU_0xFF;
            },
            //LD D, (HL)
            //#0x56:
            parentObj => {
                parentObj.registerD = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
            },
            //LD D, A
            //#0x57:
            parentObj => {
                parentObj.registerD = parentObj.registerA;
            },
            //LD E, B
            //#0x58:
            parentObj => {
                parentObj.registerE = parentObj.registerB;
            },
            //LD E, C
            //#0x59:
            parentObj => {
                parentObj.registerE = parentObj.registerC;
            },
            //LD E, D
            //#0x5A:
            parentObj => {
                parentObj.registerE = parentObj.registerD;
            },
            //LD E, E
            //#0x5B:
            parentObj => {
                //Do nothing...
            },
            //LD E, H
            //#0x5C:
            parentObj => {
                parentObj.registerE = parentObj.registersHL >> GBEMU_8;
            },
            //LD E, L
            //#0x5D:
            parentObj => {
                parentObj.registerE = parentObj.registersHL & GBEMU_0xFF;
            },
            //LD E, (HL)
            //#0x5E:
            parentObj => {
                parentObj.registerE = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
            },
            //LD E, A
            //#0x5F:
            parentObj => {
                parentObj.registerE = parentObj.registerA;
            },
            //LD H, B
            //#0x60:
            parentObj => {
                parentObj.registersHL = (parentObj.registerB << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
            },
            //LD H, C
            //#0x61:
            parentObj => {
                parentObj.registersHL = (parentObj.registerC << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
            },
            //LD H, D
            //#0x62:
            parentObj => {
                parentObj.registersHL = (parentObj.registerD << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
            },
            //LD H, E
            //#0x63:
            parentObj => {
                parentObj.registersHL = (parentObj.registerE << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
            },
            //LD H, H
            //#0x64:
            parentObj => {
                //Do nothing...
            },
            //LD H, L
            //#0x65:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF) * GBEMU_0x101;
            },
            //LD H, (HL)
            //#0x66:
            parentObj => {
                parentObj.registersHL =
                    (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
            },
            //LD H, A
            //#0x67:
            parentObj => {
                parentObj.registersHL = (parentObj.registerA << GBEMU_8) | (parentObj.registersHL & GBEMU_0xFF);
            },
            //LD L, B
            //#0x68:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.registerB;
            },
            //LD L, C
            //#0x69:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.registerC;
            },
            //LD L, D
            //#0x6A:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.registerD;
            },
            //LD L, E
            //#0x6B:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.registerE;
            },
            //LD L, H
            //#0x6C:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | (parentObj.registersHL >> GBEMU_8);
            },
            //LD L, L
            //#0x6D:
            parentObj => {
                //Do nothing...
            },
            //LD L, (HL)
            //#0x6E:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
            },
            //LD L, A
            //#0x6F:
            parentObj => {
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | parentObj.registerA;
            },
            //LD (HL), B
            //#0x70:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerB);
            },
            //LD (HL), C
            //#0x71:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerC);
            },
            //LD (HL), D
            //#0x72:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerD);
            },
            //LD (HL), E
            //#0x73:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerE);
            },
            //LD (HL), H
            //#0x74:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registersHL >> GBEMU_8);
            },
            //LD (HL), L
            //#0x75:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registersHL & GBEMU_0xFF);
            },
            //HALT
            //#0x76:
            parentObj => {
                //See if there's already an IRQ match:
                if ((parentObj.interruptsEnabled & parentObj.interruptsRequested & GBEMU_0x1F) > 0) {
                    if (!parentObj.cGBC && !parentObj.usedBootrom) {
                        //HALT bug in the DMG CPU model (Program Counter fails to increment for one instruction after HALT):
                        parentObj.skipPCIncrement = true;
                    }
                    else {
                        //CGB gets around the HALT PC bug by doubling the hidden NOP.
                        parentObj.cpuTicks += GBEMU_4;
                    }
                }
                else {
                    //CPU is stalled until the next IRQ match:
                    parentObj.calculateHALTPeriod();
                }
            },
            //LD (HL), A
            //#0x77:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.registerA);
            },
            //LD A, B
            //#0x78:
            parentObj => {
                parentObj.registerA = parentObj.registerB;
            },
            //LD A, C
            //#0x79:
            parentObj => {
                parentObj.registerA = parentObj.registerC;
            },
            //LD A, D
            //#0x7A:
            parentObj => {
                parentObj.registerA = parentObj.registerD;
            },
            //LD A, E
            //#0x7B:
            parentObj => {
                parentObj.registerA = parentObj.registerE;
            },
            //LD A, H
            //#0x7C:
            parentObj => {
                parentObj.registerA = parentObj.registersHL >> GBEMU_8;
            },
            //LD A, L
            //#0x7D:
            parentObj => {
                parentObj.registerA = parentObj.registersHL & GBEMU_0xFF;
            },
            //LD, A, (HL)
            //#0x7E:
            parentObj => {
                parentObj.registerA = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
            },
            //LD A, A
            //#0x7F:
            parentObj => {
                //Do Nothing...
            },
            //ADD A, B
            //#0x80:
            parentObj => {
                let dirtySum = parentObj.registerA + parentObj.registerB;
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADD A, C
            //#0x81:
            parentObj => {
                let dirtySum = parentObj.registerA + parentObj.registerC;
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADD A, D
            //#0x82:
            parentObj => {
                let dirtySum = parentObj.registerA + parentObj.registerD;
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADD A, E
            //#0x83:
            parentObj => {
                let dirtySum = parentObj.registerA + parentObj.registerE;
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADD A, H
            //#0x84:
            parentObj => {
                let dirtySum = parentObj.registerA + (parentObj.registersHL >> GBEMU_8);
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADD A, L
            //#0x85:
            parentObj => {
                let dirtySum = parentObj.registerA + (parentObj.registersHL & GBEMU_0xFF);
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADD A, (HL)
            //#0x86:
            parentObj => {
                let dirtySum = parentObj.registerA + parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADD A, A
            //#0x87:
            parentObj => {
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0x8) === GBEMU_0x8;
                parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
                parentObj.registerA = (parentObj.registerA << 1) & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADC A, B
            //#0x88:
            parentObj => {
                let dirtySum = parentObj.registerA + parentObj.registerB + (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (parentObj.registerB & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADC A, C
            //#0x89:
            parentObj => {
                let dirtySum = parentObj.registerA + parentObj.registerC + (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (parentObj.registerC & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADC A, D
            //#0x8A:
            parentObj => {
                let dirtySum = parentObj.registerA + parentObj.registerD + (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (parentObj.registerD & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADC A, E
            //#0x8B:
            parentObj => {
                let dirtySum = parentObj.registerA + parentObj.registerE + (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (parentObj.registerE & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADC A, H
            //#0x8C:
            parentObj => {
                let tempValue = parentObj.registersHL >> GBEMU_8;
                let dirtySum = parentObj.registerA + tempValue + (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (tempValue & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADC A, L
            //#0x8D:
            parentObj => {
                let tempValue = parentObj.registersHL & GBEMU_0xFF;
                let dirtySum = parentObj.registerA + tempValue + (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (tempValue & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADC A, (HL)
            //#0x8E:
            parentObj => {
                let tempValue = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                let dirtySum = parentObj.registerA + tempValue + (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (tempValue & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //ADC A, A
            //#0x8F:
            parentObj => {
                //shift left register A one bit for some ops here as an optimization:
                let dirtySum = (parentObj.registerA << 1) | (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (((parentObj.registerA << 1) & GBEMU_0x1E) | (parentObj.fCarry ? 1 : 0)) > GBEMU_0xF;
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //SUB A, B
            //#0x90:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerB;
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //SUB A, C
            //#0x91:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerC;
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //SUB A, D
            //#0x92:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerD;
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //SUB A, E
            //#0x93:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerE;
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //SUB A, H
            //#0x94:
            parentObj => {
                let dirtySum = parentObj.registerA - (parentObj.registersHL >> GBEMU_8);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //SUB A, L
            //#0x95:
            parentObj => {
                let dirtySum = parentObj.registerA - (parentObj.registersHL & GBEMU_0xFF);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //SUB A, (HL)
            //#0x96:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //SUB A, A
            //#0x97:
            parentObj => {
                //number - same number === 0
                parentObj.registerA = 0;
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
                parentObj.fZero = true;
                parentObj.fSubtract = true;
            },
            //SBC A, B
            //#0x98:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerB - (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (parentObj.registerB & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = true;
            },
            //SBC A, C
            //#0x99:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerC - (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (parentObj.registerC & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = true;
            },
            //SBC A, D
            //#0x9A:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerD - (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (parentObj.registerD & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = true;
            },
            //SBC A, E
            //#0x9B:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerE - (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (parentObj.registerE & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = true;
            },
            //SBC A, H
            //#0x9C:
            parentObj => {
                let tempVar = parentObj.registersHL >> GBEMU_8;
                let dirtySum = parentObj.registerA - tempVar - (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (tempVar & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = true;
            },
            //SBC A, L
            //#0x9D:
            parentObj => {
                let dirtySum = parentObj.registerA - (parentObj.registersHL & GBEMU_0xFF) - (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (parentObj.registersHL & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = true;
            },
            //SBC A, (HL)
            //#0x9E:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                let dirtySum = parentObj.registerA - tempVar - (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (tempVar & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = true;
            },
            //SBC A, A
            //#0x9F:
            parentObj => {
                //Optimized SBC A:
                if (parentObj.fCarry) {
                    parentObj.fZero = false;
                    parentObj.fSubtract = true;
                    parentObj.fHalfCarry = true;
                    parentObj.fCarry = true;
                    parentObj.registerA = GBEMU_0xFF;
                }
                else {
                    parentObj.fHalfCarry = false;
                    parentObj.fCarry = false;
                    parentObj.fSubtract = true;
                    parentObj.fZero = true;
                    parentObj.registerA = 0;
                }
            },
            //AND B
            //#0xA0:
            parentObj => {
                parentObj.registerA &= parentObj.registerB;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
            },
            //AND C
            //#0xA1:
            parentObj => {
                parentObj.registerA &= parentObj.registerC;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
            },
            //AND D
            //#0xA2:
            parentObj => {
                parentObj.registerA &= parentObj.registerD;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
            },
            //AND E
            //#0xA3:
            parentObj => {
                parentObj.registerA &= parentObj.registerE;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
            },
            //AND H
            //#0xA4:
            parentObj => {
                parentObj.registerA &= parentObj.registersHL >> GBEMU_8;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
            },
            //AND L
            //#0xA5:
            parentObj => {
                parentObj.registerA &= parentObj.registersHL;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
            },
            //AND (HL)
            //#0xA6:
            parentObj => {
                parentObj.registerA &= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
            },
            //AND A
            //#0xA7:
            parentObj => {
                //number & same number = same number
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
            },
            //XOR B
            //#0xA8:
            parentObj => {
                parentObj.registerA ^= parentObj.registerB;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
            },
            //XOR C
            //#0xA9:
            parentObj => {
                parentObj.registerA ^= parentObj.registerC;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
            },
            //XOR D
            //#0xAA:
            parentObj => {
                parentObj.registerA ^= parentObj.registerD;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
            },
            //XOR E
            //#0xAB:
            parentObj => {
                parentObj.registerA ^= parentObj.registerE;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
            },
            //XOR H
            //#0xAC:
            parentObj => {
                parentObj.registerA ^= parentObj.registersHL >> GBEMU_8;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
            },
            //XOR L
            //#0xAD:
            parentObj => {
                parentObj.registerA ^= parentObj.registersHL & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
            },
            //XOR (HL)
            //#0xAE:
            parentObj => {
                parentObj.registerA ^= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
            },
            //XOR A
            //#0xAF:
            parentObj => {
                //number ^ same number === 0
                parentObj.registerA = 0;
                parentObj.fZero = true;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
            },
            //OR B
            //#0xB0:
            parentObj => {
                parentObj.registerA |= parentObj.registerB;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
            },
            //OR C
            //#0xB1:
            parentObj => {
                parentObj.registerA |= parentObj.registerC;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
            },
            //OR D
            //#0xB2:
            parentObj => {
                parentObj.registerA |= parentObj.registerD;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
            },
            //OR E
            //#0xB3:
            parentObj => {
                parentObj.registerA |= parentObj.registerE;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
            },
            //OR H
            //#0xB4:
            parentObj => {
                parentObj.registerA |= parentObj.registersHL >> GBEMU_8;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
            },
            //OR L
            //#0xB5:
            parentObj => {
                parentObj.registerA |= parentObj.registersHL & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
            },
            //OR (HL)
            //#0xB6:
            parentObj => {
                parentObj.registerA |= parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
            },
            //OR A
            //#0xB7:
            parentObj => {
                //number | same number === same number
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
            },
            //CP B
            //#0xB8:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerB;
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //CP C
            //#0xB9:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerC;
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //CP D
            //#0xBA:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerD;
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //CP E
            //#0xBB:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.registerE;
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //CP H
            //#0xBC:
            parentObj => {
                let dirtySum = parentObj.registerA - (parentObj.registersHL >> GBEMU_8);
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //CP L
            //#0xBD:
            parentObj => {
                let dirtySum = parentObj.registerA - (parentObj.registersHL & GBEMU_0xFF);
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //CP (HL)
            //#0xBE:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //CP A
            //#0xBF:
            parentObj => {
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
                parentObj.fZero = true;
                parentObj.fSubtract = true;
            },
            //RET !FZ
            //#0xC0:
            parentObj => {
                if (!parentObj.fZero) {
                    parentObj.programCounter =
                        (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                            parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
                    parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
                    parentObj.cpuTicks += GBEMU_12;
                }
            },
            //POP BC
            //#0xC1:
            parentObj => {
                parentObj.registerC = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
                parentObj.registerB = parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF);
                parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
            },
            //JP !FZ, nn
            //#0xC2:
            parentObj => {
                if (!parentObj.fZero) {
                    parentObj.programCounter =
                        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                            parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                    parentObj.cpuTicks += GBEMU_4;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                }
            },
            //JP nn
            //#0xC3:
            parentObj => {
                parentObj.programCounter =
                    (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
            },
            //CALL !FZ, nn
            //#0xC4:
            parentObj => {
                if (!parentObj.fZero) {
                    let temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                    parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                    parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                    parentObj.programCounter = temp_pc;
                    parentObj.cpuTicks += GBEMU_12;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                }
            },
            //PUSH BC
            //#0xC5:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerB);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerC);
            },
            //ADD, n
            //#0xC6:
            parentObj => {
                let dirtySum = parentObj.registerA + parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) < (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //RST 0
            //#0xC7:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                parentObj.programCounter = 0;
            },
            //RET FZ
            //#0xC8:
            parentObj => {
                if (parentObj.fZero) {
                    parentObj.programCounter =
                        (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                            parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
                    parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
                    parentObj.cpuTicks += GBEMU_12;
                }
            },
            //RET
            //#0xC9:
            parentObj => {
                parentObj.programCounter =
                    (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                        parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
                parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
            },
            //JP FZ, nn
            //#0xCA:
            parentObj => {
                if (parentObj.fZero) {
                    parentObj.programCounter =
                        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                            parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                    parentObj.cpuTicks += GBEMU_4;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                }
            },
            //Secondary OP Code Set:
            //#0xCB:
            parentObj => {
                let opcode = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                //Increment the program counter to the next instruction:
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                //Execute secondary OP codes for the 0xCB OP code call.
                parentObj.cbOpCode[opcode](parentObj);
                //Get how many CPU cycles the current 0xCBXX op code counts for:
                parentObj.cpuTicks += parentObj.secondaryTickTable[opcode];
            },
            //CALL FZ, nn
            //#0xCC:
            parentObj => {
                if (parentObj.fZero) {
                    let temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                    parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                    parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                    parentObj.programCounter = temp_pc;
                    parentObj.cpuTicks += GBEMU_12;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                }
            },
            //CALL nn
            //#0xCD:
            parentObj => {
                let temp_pc = (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                    parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                parentObj.programCounter = temp_pc;
            },
            //ADC A, n
            //#0xCE:
            parentObj => {
                let tempValue = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                let dirtySum = parentObj.registerA + tempValue + (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) + (tempValue & GBEMU_0xF) + (parentObj.fCarry ? 1 : 0) > GBEMU_0xF;
                parentObj.fCarry = dirtySum > GBEMU_0xFF;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
            },
            //RST 0x8
            //#0xCF:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                parentObj.programCounter = 0x8;
            },
            //RET !FC
            //#0xD0:
            parentObj => {
                if (!parentObj.fCarry) {
                    parentObj.programCounter =
                        (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                            parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
                    parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
                    parentObj.cpuTicks += GBEMU_12;
                }
            },
            //POP DE
            //#0xD1:
            parentObj => {
                parentObj.registerE = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
                parentObj.registerD = parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF);
                parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
            },
            //JP !FC, nn
            //#0xD2:
            parentObj => {
                if (!parentObj.fCarry) {
                    parentObj.programCounter =
                        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                            parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                    parentObj.cpuTicks += GBEMU_4;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                }
            },
            //0xD3 - Illegal
            //#0xD3:
            parentObj => {
                cout('Illegal op code 0xD3 called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //CALL !FC, nn
            //#0xD4:
            parentObj => {
                if (!parentObj.fCarry) {
                    let tempPc = (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                    parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                    parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                    parentObj.programCounter = tempPc;
                    parentObj.cpuTicks += GBEMU_12;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                }
            },
            //PUSH DE
            //#0xD5:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerD);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerE);
            },
            //SUB A, n
            //#0xD6:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) < (dirtySum & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //RST 0x10
            //#0xD7:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                parentObj.programCounter = GBEMU_0x10;
            },
            //RET FC
            //#0xD8:
            parentObj => {
                if (parentObj.fCarry) {
                    parentObj.programCounter =
                        (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                            parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
                    parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
                    parentObj.cpuTicks += GBEMU_12;
                }
            },
            //RETI
            //#0xD9:
            parentObj => {
                parentObj.programCounter =
                    (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                        parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
                parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
                //Immediate for HALT:
                parentObj.irqEnableDelay =
                    parentObj.irqEnableDelay === GBEMU_2 || parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) === GBEMU_0x76 ?
                        1 :
                        GBEMU_2;
            },
            //JP FC, nn
            //#0xDA:
            parentObj => {
                if (parentObj.fCarry) {
                    parentObj.programCounter =
                        (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                            parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                    parentObj.cpuTicks += GBEMU_4;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                }
            },
            //0xDB - Illegal
            //#0xDB:
            parentObj => {
                cout('Illegal op code 0xDB called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //CALL FC, nn
            //#0xDC:
            parentObj => {
                if (parentObj.fCarry) {
                    let tempPc = (parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                        parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                    parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                    parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                    parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                    parentObj.programCounter = tempPc;
                    parentObj.cpuTicks += GBEMU_12;
                }
                else {
                    parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
                }
            },
            //0xDD - Illegal
            //#0xDD:
            parentObj => {
                cout('Illegal op code 0xDD called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //SBC A, n
            //#0xDE:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                let dirtySum = parentObj.registerA - tempVar - (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = (parentObj.registerA & GBEMU_0xF) - (tempVar & GBEMU_0xF) - (parentObj.fCarry ? 1 : 0) < 0;
                parentObj.fCarry = dirtySum < 0;
                parentObj.registerA = dirtySum & GBEMU_0xFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = true;
            },
            //RST 0x18
            //#0xDF:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                parentObj.programCounter = GBEMU_0x18;
            },
            //LDH (n), A
            //#0xE0:
            parentObj => {
                parentObj.memoryHighWrite(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter), parentObj.registerA);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
            },
            //POP HL
            //#0xE1:
            parentObj => {
                parentObj.registersHL =
                    (parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                        parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
                parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
            },
            //LD (0xFF00 + C), A
            //#0xE2:
            parentObj => {
                parentObj.memoryHighWriter[parentObj.registerC](parentObj, parentObj.registerC, parentObj.registerA);
            },
            //0xE3 - Illegal
            //#0xE3:
            parentObj => {
                cout('Illegal op code 0xE3 called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //0xE4 - Illegal
            //#0xE4:
            parentObj => {
                cout('Illegal op code 0xE4 called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //PUSH HL
            //#0xE5:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registersHL >> GBEMU_8);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registersHL & GBEMU_0xFF);
            },
            //AND n
            //#0xE6:
            parentObj => {
                parentObj.registerA &= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
            },
            //RST 0x20
            //#0xE7:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                parentObj.programCounter = GBEMU_0x20;
            },
            //ADD SP, n
            //#0xE8:
            parentObj => {
                let tempValue2 = (parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24;
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                let tempValue = (parentObj.stackPointer + tempValue2) & GBEMU_0xFFFF;
                tempValue2 = parentObj.stackPointer ^ tempValue2 ^ tempValue;
                parentObj.stackPointer = tempValue;
                parentObj.fCarry = (tempValue2 & GBEMU_0x100) === GBEMU_0x100;
                parentObj.fHalfCarry = (tempValue2 & GBEMU_0x10) === GBEMU_0x10;
                parentObj.fZero = false;
                parentObj.fSubtract = false;
            },
            //JP, (HL)
            //#0xE9:
            parentObj => {
                parentObj.programCounter = parentObj.registersHL;
            },
            //LD n, A
            //#0xEA:
            parentObj => {
                parentObj.memoryWrite((parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                    parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter), parentObj.registerA);
                parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
            },
            //0xEB - Illegal
            //#0xEB:
            parentObj => {
                cout('Illegal op code 0xEB called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //0xEC - Illegal
            //#0xEC:
            parentObj => {
                cout('Illegal op code 0xEC called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //0xED - Illegal
            //#0xED:
            parentObj => {
                cout('Illegal op code 0xED called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //XOR n
            //#0xEE:
            parentObj => {
                parentObj.registerA ^= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fSubtract = false;
                parentObj.fHalfCarry = false;
                parentObj.fCarry = false;
            },
            //RST 0x28
            //#0xEF:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                parentObj.programCounter = GBEMU_0x28;
            },
            //LDH A, (n)
            //#0xF0:
            parentObj => {
                parentObj.registerA = parentObj.memoryHighRead(parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
            },
            //POP AF
            //#0xF1:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.stackPointer](parentObj, parentObj.stackPointer);
                parentObj.fZero = tempVar > GBEMU_0x7F;
                parentObj.fSubtract = (tempVar & GBEMU_0x40) === GBEMU_0x40;
                parentObj.fHalfCarry = (tempVar & GBEMU_0x20) === GBEMU_0x20;
                parentObj.fCarry = (tempVar & GBEMU_0x10) === GBEMU_0x10;
                parentObj.registerA = parentObj.memoryRead((parentObj.stackPointer + 1) & GBEMU_0xFFFF);
                parentObj.stackPointer = (parentObj.stackPointer + GBEMU_2) & GBEMU_0xFFFF;
            },
            //LD A, (0xFF00 + C)
            //#0xF2:
            parentObj => {
                parentObj.registerA = parentObj.memoryHighReader[parentObj.registerC](parentObj, parentObj.registerC);
            },
            //DI
            //#0xF3:
            parentObj => {
                parentObj.ime = false;
                parentObj.irqEnableDelay = 0;
            },
            //0xF4 - Illegal
            //#0xF4:
            parentObj => {
                cout('Illegal op code 0xF4 called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //PUSH AF
            //#0xF5:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.registerA);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, (parentObj.fZero ? GBEMU_0x80 : 0) |
                    (parentObj.fSubtract ? GBEMU_0x40 : 0) |
                    (parentObj.fHalfCarry ? GBEMU_0x20 : 0) |
                    (parentObj.fCarry ? GBEMU_0x10 : 0));
            },
            //OR n
            //#0xF6:
            parentObj => {
                parentObj.registerA |= parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                parentObj.fSubtract = false;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
            },
            //RST 0x30
            //#0xF7:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                parentObj.programCounter = GBEMU_0x30;
            },
            //LDHL SP, n
            //#0xF8:
            parentObj => {
                let tempVar = (parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) << GBEMU_24) >> GBEMU_24;
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                parentObj.registersHL = (parentObj.stackPointer + tempVar) & GBEMU_0xFFFF;
                tempVar = parentObj.stackPointer ^ tempVar ^ parentObj.registersHL;
                parentObj.fCarry = (tempVar & GBEMU_0x100) === GBEMU_0x100;
                parentObj.fHalfCarry = (tempVar & GBEMU_0x10) === GBEMU_0x10;
                parentObj.fZero = false;
                parentObj.fSubtract = false;
            },
            //LD SP, HL
            //#0xF9:
            parentObj => {
                parentObj.stackPointer = parentObj.registersHL;
            },
            //LD A, (nn)
            //#0xFA:
            parentObj => {
                parentObj.registerA = parentObj.memoryRead((parentObj.memoryRead((parentObj.programCounter + 1) & GBEMU_0xFFFF) << GBEMU_8) |
                    parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter));
                parentObj.programCounter = (parentObj.programCounter + GBEMU_2) & GBEMU_0xFFFF;
            },
            //EI
            //#0xFB:
            parentObj => {
                //Immediate for HALT:
                parentObj.irqEnableDelay =
                    parentObj.irqEnableDelay === GBEMU_2 || parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter) === GBEMU_0x76 ?
                        1 :
                        GBEMU_2;
            },
            //0xFC - Illegal
            //#0xFC:
            parentObj => {
                cout('Illegal op code 0xFC called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //0xFD - Illegal
            //#0xFD:
            parentObj => {
                cout('Illegal op code 0xFD called, pausing emulation.', GBEMU_2);
                pausePlay();
            },
            //CP n
            //#0xFE:
            parentObj => {
                let dirtySum = parentObj.registerA - parentObj.memoryReader[parentObj.programCounter](parentObj, parentObj.programCounter);
                parentObj.programCounter = (parentObj.programCounter + 1) & GBEMU_0xFFFF;
                parentObj.fHalfCarry = (dirtySum & GBEMU_0xF) > (parentObj.registerA & GBEMU_0xF);
                parentObj.fCarry = dirtySum < 0;
                parentObj.fZero = dirtySum === 0;
                parentObj.fSubtract = true;
            },
            //RST 0x38
            //#0xFF:
            parentObj => {
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter >> GBEMU_8);
                parentObj.stackPointer = (parentObj.stackPointer - 1) & GBEMU_0xFFFF;
                parentObj.memoryWriter[parentObj.stackPointer](parentObj, parentObj.stackPointer, parentObj.programCounter & GBEMU_0xFF);
                parentObj.programCounter = GBEMU_0x38;
            }
        ];
        this.cbOpCode = [
            //RLC B
            //#0x00:
            parentObj => {
                parentObj.fCarry = parentObj.registerB > GBEMU_0x7F;
                parentObj.registerB = ((parentObj.registerB << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerB === 0;
            },
            //RLC C
            //#0x01:
            parentObj => {
                parentObj.fCarry = parentObj.registerC > GBEMU_0x7F;
                parentObj.registerC = ((parentObj.registerC << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerC === 0;
            },
            //RLC D
            //#0x02:
            parentObj => {
                parentObj.fCarry = parentObj.registerD > GBEMU_0x7F;
                parentObj.registerD = ((parentObj.registerD << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerD === 0;
            },
            //RLC E
            //#0x03:
            parentObj => {
                parentObj.fCarry = parentObj.registerE > GBEMU_0x7F;
                parentObj.registerE = ((parentObj.registerE << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerE === 0;
            },
            //RLC H
            //#0x04:
            parentObj => {
                parentObj.fCarry = parentObj.registersHL > GBEMU_0x7FFF;
                parentObj.registersHL = ((parentObj.registersHL << 1) & GBEMU_0xFE00) | (parentObj.fCarry ? GBEMU_0x100 : 0) | (parentObj.registersHL & GBEMU_0xFF);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
            },
            //RLC L
            //#0x05:
            parentObj => {
                parentObj.fCarry = (parentObj.registersHL & GBEMU_0x80) === GBEMU_0x80;
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | ((parentObj.registersHL << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
            },
            //RLC (HL)
            //#0x06:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fCarry = tempVar > GBEMU_0x7F;
                tempVar = ((tempVar << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = tempVar === 0;
            },
            //RLC A
            //#0x07:
            parentObj => {
                parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
                parentObj.registerA = ((parentObj.registerA << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerA === 0;
            },
            //RRC B
            //#0x08:
            parentObj => {
                parentObj.fCarry = (parentObj.registerB & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerB = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerB >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerB === 0;
            },
            //RRC C
            //#0x09:
            parentObj => {
                parentObj.fCarry = (parentObj.registerC & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerC = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerC >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerC === 0;
            },
            //RRC D
            //#0x0A:
            parentObj => {
                parentObj.fCarry = (parentObj.registerD & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerD = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerD >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerD === 0;
            },
            //RRC E
            //#0x0B:
            parentObj => {
                parentObj.fCarry = (parentObj.registerE & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerE = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerE >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerE === 0;
            },
            //RRC H
            //#0x0C:
            parentObj => {
                parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0100) === GBEMU_0x0100;
                parentObj.registersHL = (parentObj.fCarry ? GBEMU_0x8000 : 0) | ((parentObj.registersHL >> 1) & GBEMU_0xFF00) | (parentObj.registersHL & GBEMU_0xFF);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
            },
            //RRC L
            //#0x0D:
            parentObj => {
                parentObj.fCarry = (parentObj.registersHL & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | (parentObj.fCarry ? GBEMU_0x80 : 0) | ((parentObj.registersHL & GBEMU_0xFF) >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
            },
            //RRC (HL)
            //#0x0E:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fCarry = (tempVar & GBEMU_0x01) === GBEMU_0x01;
                tempVar = (parentObj.fCarry ? GBEMU_0x80 : 0) | (tempVar >> 1);
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = tempVar === 0;
            },
            //RRC A
            //#0x0F:
            parentObj => {
                parentObj.fCarry = (parentObj.registerA & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerA = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerA >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerA === 0;
            },
            //RL B
            //#0x10:
            parentObj => {
                let newfCarry = parentObj.registerB > GBEMU_0x7F;
                parentObj.registerB = ((parentObj.registerB << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerB === 0;
            },
            //RL C
            //#0x11:
            parentObj => {
                let newfCarry = parentObj.registerC > GBEMU_0x7F;
                parentObj.registerC = ((parentObj.registerC << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerC === 0;
            },
            //RL D
            //#0x12:
            parentObj => {
                let newfCarry = parentObj.registerD > GBEMU_0x7F;
                parentObj.registerD = ((parentObj.registerD << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerD === 0;
            },
            //RL E
            //#0x13:
            parentObj => {
                let newfCarry = parentObj.registerE > GBEMU_0x7F;
                parentObj.registerE = ((parentObj.registerE << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerE === 0;
            },
            //RL H
            //#0x14:
            parentObj => {
                let newfCarry = parentObj.registersHL > GBEMU_0x7FFF;
                parentObj.registersHL = ((parentObj.registersHL << 1) & GBEMU_0xFE00) | (parentObj.fCarry ? GBEMU_0x100 : 0) | (parentObj.registersHL & GBEMU_0xFF);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
            },
            //RL L
            //#0x15:
            parentObj => {
                let newfCarry = (parentObj.registersHL & GBEMU_0x80) === GBEMU_0x80;
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | ((parentObj.registersHL << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
            },
            //RL (HL)
            //#0x16:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                let newfCarry = tempVar > GBEMU_0x7F;
                tempVar = ((tempVar << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fCarry = newfCarry;
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = tempVar === 0;
            },
            //RL A
            //#0x17:
            parentObj => {
                let newfCarry = parentObj.registerA > GBEMU_0x7F;
                parentObj.registerA = ((parentObj.registerA << 1) & GBEMU_0xFF) | (parentObj.fCarry ? 1 : 0);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerA === 0;
            },
            //RR B
            //#0x18:
            parentObj => {
                let newfCarry = (parentObj.registerB & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerB = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerB >> 1);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerB === 0;
            },
            //RR C
            //#0x19:
            parentObj => {
                let newfCarry = (parentObj.registerC & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerC = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerC >> 1);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerC === 0;
            },
            //RR D
            //#0x1A:
            parentObj => {
                let newfCarry = (parentObj.registerD & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerD = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerD >> 1);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerD === 0;
            },
            //RR E
            //#0x1B:
            parentObj => {
                let newfCarry = (parentObj.registerE & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerE = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerE >> 1);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerE === 0;
            },
            //RR H
            //#0x1C:
            parentObj => {
                let newfCarry = (parentObj.registersHL & GBEMU_0x0100) === GBEMU_0x0100;
                parentObj.registersHL = (parentObj.fCarry ? GBEMU_0x8000 : 0) | ((parentObj.registersHL >> 1) & GBEMU_0xFF00) | (parentObj.registersHL & GBEMU_0xFF);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
            },
            //RR L
            //#0x1D:
            parentObj => {
                let newfCarry = (parentObj.registersHL & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | (parentObj.fCarry ? GBEMU_0x80 : 0) | ((parentObj.registersHL & GBEMU_0xFF) >> 1);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
            },
            //RR (HL)
            //#0x1E:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                let newfCarry = (tempVar & GBEMU_0x01) === GBEMU_0x01;
                tempVar = (parentObj.fCarry ? GBEMU_0x80 : 0) | (tempVar >> 1);
                parentObj.fCarry = newfCarry;
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = tempVar === 0;
            },
            //RR A
            //#0x1F:
            parentObj => {
                let newfCarry = (parentObj.registerA & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerA = (parentObj.fCarry ? GBEMU_0x80 : 0) | (parentObj.registerA >> 1);
                parentObj.fCarry = newfCarry;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerA === 0;
            },
            //SLA B
            //#0x20:
            parentObj => {
                parentObj.fCarry = parentObj.registerB > GBEMU_0x7F;
                parentObj.registerB = (parentObj.registerB << 1) & GBEMU_0xFF;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerB === 0;
            },
            //SLA C
            //#0x21:
            parentObj => {
                parentObj.fCarry = parentObj.registerC > GBEMU_0x7F;
                parentObj.registerC = (parentObj.registerC << 1) & GBEMU_0xFF;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerC === 0;
            },
            //SLA D
            //#0x22:
            parentObj => {
                parentObj.fCarry = parentObj.registerD > GBEMU_0x7F;
                parentObj.registerD = (parentObj.registerD << 1) & GBEMU_0xFF;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerD === 0;
            },
            //SLA E
            //#0x23:
            parentObj => {
                parentObj.fCarry = parentObj.registerE > GBEMU_0x7F;
                parentObj.registerE = (parentObj.registerE << 1) & GBEMU_0xFF;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerE === 0;
            },
            //SLA H
            //#0x24:
            parentObj => {
                parentObj.fCarry = parentObj.registersHL > GBEMU_0x7FFF;
                parentObj.registersHL = ((parentObj.registersHL << 1) & GBEMU_0xFE00) | (parentObj.registersHL & GBEMU_0xFF);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
            },
            //SLA L
            //#0x25:
            parentObj => {
                parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0080) === GBEMU_0x0080;
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | ((parentObj.registersHL << 1) & GBEMU_0xFF);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
            },
            //SLA (HL)
            //#0x26:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fCarry = tempVar > GBEMU_0x7F;
                tempVar = (tempVar << 1) & GBEMU_0xFF;
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = tempVar === 0;
            },
            //SLA A
            //#0x27:
            parentObj => {
                parentObj.fCarry = parentObj.registerA > GBEMU_0x7F;
                parentObj.registerA = (parentObj.registerA << 1) & GBEMU_0xFF;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerA === 0;
            },
            //SRA B
            //#0x28:
            parentObj => {
                parentObj.fCarry = (parentObj.registerB & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerB = (parentObj.registerB & GBEMU_0x80) | (parentObj.registerB >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerB === 0;
            },
            //SRA C
            //#0x29:
            parentObj => {
                parentObj.fCarry = (parentObj.registerC & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerC = (parentObj.registerC & GBEMU_0x80) | (parentObj.registerC >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerC === 0;
            },
            //SRA D
            //#0x2A:
            parentObj => {
                parentObj.fCarry = (parentObj.registerD & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerD = (parentObj.registerD & GBEMU_0x80) | (parentObj.registerD >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerD === 0;
            },
            //SRA E
            //#0x2B:
            parentObj => {
                parentObj.fCarry = (parentObj.registerE & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerE = (parentObj.registerE & GBEMU_0x80) | (parentObj.registerE >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerE === 0;
            },
            //SRA H
            //#0x2C:
            parentObj => {
                parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0100) === GBEMU_0x0100;
                parentObj.registersHL = ((parentObj.registersHL >> 1) & GBEMU_0xFF00) | (parentObj.registersHL & GBEMU_0x80FF);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
            },
            //SRA L
            //#0x2D:
            parentObj => {
                parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0001) === GBEMU_0x0001;
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF80) | ((parentObj.registersHL & GBEMU_0xFF) >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
            },
            //SRA (HL)
            //#0x2E:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fCarry = (tempVar & GBEMU_0x01) === GBEMU_0x01;
                tempVar = (tempVar & GBEMU_0x80) | (tempVar >> 1);
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = tempVar === 0;
            },
            //SRA A
            //#0x2F:
            parentObj => {
                parentObj.fCarry = (parentObj.registerA & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerA = (parentObj.registerA & GBEMU_0x80) | (parentObj.registerA >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerA === 0;
            },
            //SWAP B
            //#0x30:
            parentObj => {
                parentObj.registerB = ((parentObj.registerB & GBEMU_0xF) << GBEMU_4) | (parentObj.registerB >> GBEMU_4);
                parentObj.fZero = parentObj.registerB === 0;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
            },
            //SWAP C
            //#0x31:
            parentObj => {
                parentObj.registerC = ((parentObj.registerC & GBEMU_0xF) << GBEMU_4) | (parentObj.registerC >> GBEMU_4);
                parentObj.fZero = parentObj.registerC === 0;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
            },
            //SWAP D
            //#0x32:
            parentObj => {
                parentObj.registerD = ((parentObj.registerD & GBEMU_0xF) << GBEMU_4) | (parentObj.registerD >> GBEMU_4);
                parentObj.fZero = parentObj.registerD === 0;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
            },
            //SWAP E
            //#0x33:
            parentObj => {
                parentObj.registerE = ((parentObj.registerE & GBEMU_0xF) << GBEMU_4) | (parentObj.registerE >> GBEMU_4);
                parentObj.fZero = parentObj.registerE === 0;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
            },
            //SWAP H
            //#0x34:
            parentObj => {
                parentObj.registersHL =
                    ((parentObj.registersHL & GBEMU_0xF00) << GBEMU_4) | ((parentObj.registersHL & GBEMU_0xF000) >> GBEMU_4) | (parentObj.registersHL & GBEMU_0xFF);
                parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
            },
            //SWAP L
            //#0x35:
            parentObj => {
                parentObj.registersHL =
                    (parentObj.registersHL & GBEMU_0xFF00) | ((parentObj.registersHL & GBEMU_0xF) << GBEMU_4) | ((parentObj.registersHL & GBEMU_0xF0) >> GBEMU_4);
                parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
            },
            //SWAP (HL)
            //#0x36:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                tempVar = ((tempVar & GBEMU_0xF) << GBEMU_4) | (tempVar >> GBEMU_4);
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar);
                parentObj.fZero = tempVar === 0;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
            },
            //SWAP A
            //#0x37:
            parentObj => {
                parentObj.registerA = ((parentObj.registerA & GBEMU_0xF) << GBEMU_4) | (parentObj.registerA >> GBEMU_4);
                parentObj.fZero = parentObj.registerA === 0;
                parentObj.fCarry = false;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
            },
            //SRL B
            //#0x38:
            parentObj => {
                parentObj.fCarry = (parentObj.registerB & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerB >>= 1;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerB === 0;
            },
            //SRL C
            //#0x39:
            parentObj => {
                parentObj.fCarry = (parentObj.registerC & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerC >>= 1;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerC === 0;
            },
            //SRL D
            //#0x3A:
            parentObj => {
                parentObj.fCarry = (parentObj.registerD & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerD >>= 1;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerD === 0;
            },
            //SRL E
            //#0x3B:
            parentObj => {
                parentObj.fCarry = (parentObj.registerE & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerE >>= 1;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerE === 0;
            },
            //SRL H
            //#0x3C:
            parentObj => {
                parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0100) === GBEMU_0x0100;
                parentObj.registersHL = ((parentObj.registersHL >> 1) & GBEMU_0xFF00) | (parentObj.registersHL & GBEMU_0xFF);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registersHL < GBEMU_0x100;
            },
            //SRL L
            //#0x3D:
            parentObj => {
                parentObj.fCarry = (parentObj.registersHL & GBEMU_0x0001) === GBEMU_0x0001;
                parentObj.registersHL = (parentObj.registersHL & GBEMU_0xFF00) | ((parentObj.registersHL & GBEMU_0xFF) >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0xFF) === 0;
            },
            //SRL (HL)
            //#0x3E:
            parentObj => {
                let tempVar = parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL);
                parentObj.fCarry = (tempVar & GBEMU_0x01) === GBEMU_0x01;
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, tempVar >> 1);
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = tempVar < GBEMU_2;
            },
            //SRL A
            //#0x3F:
            parentObj => {
                parentObj.fCarry = (parentObj.registerA & GBEMU_0x01) === GBEMU_0x01;
                parentObj.registerA >>= 1;
                parentObj.fHalfCarry = false;
                parentObj.fSubtract = false;
                parentObj.fZero = parentObj.registerA === 0;
            },
            //BIT 0, B
            //#0x40:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerB & GBEMU_0x01) === 0;
            },
            //BIT 0, C
            //#0x41:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerC & GBEMU_0x01) === 0;
            },
            //BIT 0, D
            //#0x42:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerD & GBEMU_0x01) === 0;
            },
            //BIT 0, E
            //#0x43:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerE & GBEMU_0x01) === 0;
            },
            //BIT 0, H
            //#0x44:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0100) === 0;
            },
            //BIT 0, L
            //#0x45:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0001) === 0;
            },
            //BIT 0, (HL)
            //#0x46:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x01) === 0;
            },
            //BIT 0, A
            //#0x47:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerA & GBEMU_0x01) === 0;
            },
            //BIT 1, B
            //#0x48:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerB & GBEMU_0x02) === 0;
            },
            //BIT 1, C
            //#0x49:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerC & GBEMU_0x02) === 0;
            },
            //BIT 1, D
            //#0x4A:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerD & GBEMU_0x02) === 0;
            },
            //BIT 1, E
            //#0x4B:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerE & GBEMU_0x02) === 0;
            },
            //BIT 1, H
            //#0x4C:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0200) === 0;
            },
            //BIT 1, L
            //#0x4D:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0002) === 0;
            },
            //BIT 1, (HL)
            //#0x4E:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x02) === 0;
            },
            //BIT 1, A
            //#0x4F:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerA & GBEMU_0x02) === 0;
            },
            //BIT GBEMU_2, B
            //#0x50:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerB & GBEMU_0x04) === 0;
            },
            //BIT GBEMU_2, C
            //#0x51:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerC & GBEMU_0x04) === 0;
            },
            //BIT GBEMU_2, D
            //#0x52:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerD & GBEMU_0x04) === 0;
            },
            //BIT GBEMU_2, E
            //#0x53:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerE & GBEMU_0x04) === 0;
            },
            //BIT GBEMU_2, H
            //#0x54:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0400) === 0;
            },
            //BIT GBEMU_2, L
            //#0x55:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0004) === 0;
            },
            //BIT GBEMU_2, (HL)
            //#0x56:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x04) === 0;
            },
            //BIT GBEMU_2, A
            //#0x57:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerA & GBEMU_0x04) === 0;
            },
            //BIT GBEMU_3, B
            //#0x58:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerB & GBEMU_0x08) === 0;
            },
            //BIT GBEMU_3, C
            //#0x59:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerC & GBEMU_0x08) === 0;
            },
            //BIT GBEMU_3, D
            //#0x5A:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerD & GBEMU_0x08) === 0;
            },
            //BIT GBEMU_3, E
            //#0x5B:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerE & GBEMU_0x08) === 0;
            },
            //BIT GBEMU_3, H
            //#0x5C:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0800) === 0;
            },
            //BIT GBEMU_3, L
            //#0x5D:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0008) === 0;
            },
            //BIT GBEMU_3, (HL)
            //#0x5E:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x08) === 0;
            },
            //BIT GBEMU_3, A
            //#0x5F:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerA & GBEMU_0x08) === 0;
            },
            //BIT GBEMU_4, B
            //#0x60:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerB & GBEMU_0x10) === 0;
            },
            //BIT GBEMU_4, C
            //#0x61:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerC & GBEMU_0x10) === 0;
            },
            //BIT GBEMU_4, D
            //#0x62:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerD & GBEMU_0x10) === 0;
            },
            //BIT GBEMU_4, E
            //#0x63:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerE & GBEMU_0x10) === 0;
            },
            //BIT GBEMU_4, H
            //#0x64:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x1000) === 0;
            },
            //BIT GBEMU_4, L
            //#0x65:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0010) === 0;
            },
            //BIT GBEMU_4, (HL)
            //#0x66:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x10) === 0;
            },
            //BIT GBEMU_4, A
            //#0x67:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerA & GBEMU_0x10) === 0;
            },
            //BIT GBEMU_5, B
            //#0x68:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerB & GBEMU_0x20) === 0;
            },
            //BIT GBEMU_5, C
            //#0x69:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerC & GBEMU_0x20) === 0;
            },
            //BIT GBEMU_5, D
            //#0x6A:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerD & GBEMU_0x20) === 0;
            },
            //BIT GBEMU_5, E
            //#0x6B:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerE & GBEMU_0x20) === 0;
            },
            //BIT GBEMU_5, H
            //#0x6C:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x2000) === 0;
            },
            //BIT GBEMU_5, L
            //#0x6D:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0020) === 0;
            },
            //BIT GBEMU_5, (HL)
            //#0x6E:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x20) === 0;
            },
            //BIT GBEMU_5, A
            //#0x6F:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerA & GBEMU_0x20) === 0;
            },
            //BIT GBEMU_6, B
            //#0x70:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerB & GBEMU_0x40) === 0;
            },
            //BIT GBEMU_6, C
            //#0x71:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerC & GBEMU_0x40) === 0;
            },
            //BIT GBEMU_6, D
            //#0x72:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerD & GBEMU_0x40) === 0;
            },
            //BIT GBEMU_6, E
            //#0x73:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerE & GBEMU_0x40) === 0;
            },
            //BIT GBEMU_6, H
            //#0x74:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x4000) === 0;
            },
            //BIT GBEMU_6, L
            //#0x75:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0040) === 0;
            },
            //BIT GBEMU_6, (HL)
            //#0x76:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x40) === 0;
            },
            //BIT GBEMU_6, A
            //#0x77:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerA & GBEMU_0x40) === 0;
            },
            //BIT GBEMU_7, B
            //#0x78:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerB & GBEMU_0x80) === 0;
            },
            //BIT GBEMU_7, C
            //#0x79:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerC & GBEMU_0x80) === 0;
            },
            //BIT GBEMU_7, D
            //#0x7A:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerD & GBEMU_0x80) === 0;
            },
            //BIT GBEMU_7, E
            //#0x7B:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerE & GBEMU_0x80) === 0;
            },
            //BIT GBEMU_7, H
            //#0x7C:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x8000) === 0;
            },
            //BIT GBEMU_7, L
            //#0x7D:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registersHL & GBEMU_0x0080) === 0;
            },
            //BIT GBEMU_7, (HL)
            //#0x7E:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x80) === 0;
            },
            //BIT GBEMU_7, A
            //#0x7F:
            parentObj => {
                parentObj.fHalfCarry = true;
                parentObj.fSubtract = false;
                parentObj.fZero = (parentObj.registerA & GBEMU_0x80) === 0;
            },
            //RES 0, B
            //#0x80:
            parentObj => {
                parentObj.registerB &= GBEMU_0xFE;
            },
            //RES 0, C
            //#0x81:
            parentObj => {
                parentObj.registerC &= GBEMU_0xFE;
            },
            //RES 0, D
            //#0x82:
            parentObj => {
                parentObj.registerD &= GBEMU_0xFE;
            },
            //RES 0, E
            //#0x83:
            parentObj => {
                parentObj.registerE &= GBEMU_0xFE;
            },
            //RES 0, H
            //#0x84:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFEFF;
            },
            //RES 0, L
            //#0x85:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFFFE;
            },
            //RES 0, (HL)
            //#0x86:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xFE);
            },
            //RES 0, A
            //#0x87:
            parentObj => {
                parentObj.registerA &= GBEMU_0xFE;
            },
            //RES 1, B
            //#0x88:
            parentObj => {
                parentObj.registerB &= GBEMU_0xFD;
            },
            //RES 1, C
            //#0x89:
            parentObj => {
                parentObj.registerC &= GBEMU_0xFD;
            },
            //RES 1, D
            //#0x8A:
            parentObj => {
                parentObj.registerD &= GBEMU_0xFD;
            },
            //RES 1, E
            //#0x8B:
            parentObj => {
                parentObj.registerE &= GBEMU_0xFD;
            },
            //RES 1, H
            //#0x8C:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFDFF;
            },
            //RES 1, L
            //#0x8D:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFFFD;
            },
            //RES 1, (HL)
            //#0x8E:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xFD);
            },
            //RES 1, A
            //#0x8F:
            parentObj => {
                parentObj.registerA &= GBEMU_0xFD;
            },
            //RES GBEMU_2, B
            //#0x90:
            parentObj => {
                parentObj.registerB &= GBEMU_0xFB;
            },
            //RES GBEMU_2, C
            //#0x91:
            parentObj => {
                parentObj.registerC &= GBEMU_0xFB;
            },
            //RES GBEMU_2, D
            //#0x92:
            parentObj => {
                parentObj.registerD &= GBEMU_0xFB;
            },
            //RES GBEMU_2, E
            //#0x93:
            parentObj => {
                parentObj.registerE &= GBEMU_0xFB;
            },
            //RES GBEMU_2, H
            //#0x94:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFBFF;
            },
            //RES GBEMU_2, L
            //#0x95:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFFFB;
            },
            //RES GBEMU_2, (HL)
            //#0x96:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xFB);
            },
            //RES GBEMU_2, A
            //#0x97:
            parentObj => {
                parentObj.registerA &= GBEMU_0xFB;
            },
            //RES GBEMU_3, B
            //#0x98:
            parentObj => {
                parentObj.registerB &= GBEMU_0xF7;
            },
            //RES GBEMU_3, C
            //#0x99:
            parentObj => {
                parentObj.registerC &= GBEMU_0xF7;
            },
            //RES GBEMU_3, D
            //#0x9A:
            parentObj => {
                parentObj.registerD &= GBEMU_0xF7;
            },
            //RES GBEMU_3, E
            //#0x9B:
            parentObj => {
                parentObj.registerE &= GBEMU_0xF7;
            },
            //RES GBEMU_3, H
            //#0x9C:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xF7FF;
            },
            //RES GBEMU_3, L
            //#0x9D:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFFF7;
            },
            //RES GBEMU_3, (HL)
            //#0x9E:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xF7);
            },
            //RES GBEMU_3, A
            //#0x9F:
            parentObj => {
                parentObj.registerA &= GBEMU_0xF7;
            },
            //RES GBEMU_3, B
            //#0xA0:
            parentObj => {
                parentObj.registerB &= GBEMU_0xEF;
            },
            //RES GBEMU_4, C
            //#0xA1:
            parentObj => {
                parentObj.registerC &= GBEMU_0xEF;
            },
            //RES GBEMU_4, D
            //#0xA2:
            parentObj => {
                parentObj.registerD &= GBEMU_0xEF;
            },
            //RES GBEMU_4, E
            //#0xA3:
            parentObj => {
                parentObj.registerE &= GBEMU_0xEF;
            },
            //RES GBEMU_4, H
            //#0xA4:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xEFFF;
            },
            //RES GBEMU_4, L
            //#0xA5:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFFEF;
            },
            //RES GBEMU_4, (HL)
            //#0xA6:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xEF);
            },
            //RES GBEMU_4, A
            //#0xA7:
            parentObj => {
                parentObj.registerA &= GBEMU_0xEF;
            },
            //RES GBEMU_5, B
            //#0xA8:
            parentObj => {
                parentObj.registerB &= GBEMU_0xDF;
            },
            //RES GBEMU_5, C
            //#0xA9:
            parentObj => {
                parentObj.registerC &= GBEMU_0xDF;
            },
            //RES GBEMU_5, D
            //#0xAA:
            parentObj => {
                parentObj.registerD &= GBEMU_0xDF;
            },
            //RES GBEMU_5, E
            //#0xAB:
            parentObj => {
                parentObj.registerE &= GBEMU_0xDF;
            },
            //RES GBEMU_5, H
            //#0xAC:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xDFFF;
            },
            //RES GBEMU_5, L
            //#0xAD:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFFDF;
            },
            //RES GBEMU_5, (HL)
            //#0xAE:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xDF);
            },
            //RES GBEMU_5, A
            //#0xAF:
            parentObj => {
                parentObj.registerA &= GBEMU_0xDF;
            },
            //RES GBEMU_6, B
            //#0xB0:
            parentObj => {
                parentObj.registerB &= GBEMU_0xBF;
            },
            //RES GBEMU_6, C
            //#0xB1:
            parentObj => {
                parentObj.registerC &= GBEMU_0xBF;
            },
            //RES GBEMU_6, D
            //#0xB2:
            parentObj => {
                parentObj.registerD &= GBEMU_0xBF;
            },
            //RES GBEMU_6, E
            //#0xB3:
            parentObj => {
                parentObj.registerE &= GBEMU_0xBF;
            },
            //RES GBEMU_6, H
            //#0xB4:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xBFFF;
            },
            //RES GBEMU_6, L
            //#0xB5:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFFBF;
            },
            //RES GBEMU_6, (HL)
            //#0xB6:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0xBF);
            },
            //RES GBEMU_6, A
            //#0xB7:
            parentObj => {
                parentObj.registerA &= GBEMU_0xBF;
            },
            //RES GBEMU_7, B
            //#0xB8:
            parentObj => {
                parentObj.registerB &= GBEMU_0x7F;
            },
            //RES GBEMU_7, C
            //#0xB9:
            parentObj => {
                parentObj.registerC &= GBEMU_0x7F;
            },
            //RES GBEMU_7, D
            //#0xBA:
            parentObj => {
                parentObj.registerD &= GBEMU_0x7F;
            },
            //RES GBEMU_7, E
            //#0xBB:
            parentObj => {
                parentObj.registerE &= GBEMU_0x7F;
            },
            //RES GBEMU_7, H
            //#0xBC:
            parentObj => {
                parentObj.registersHL &= GBEMU_0x7FFF;
            },
            //RES GBEMU_7, L
            //#0xBD:
            parentObj => {
                parentObj.registersHL &= GBEMU_0xFF7F;
            },
            //RES GBEMU_7, (HL)
            //#0xBE:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) & GBEMU_0x7F);
            },
            //RES GBEMU_7, A
            //#0xBF:
            parentObj => {
                parentObj.registerA &= GBEMU_0x7F;
            },
            //SET 0, B
            //#0xC0:
            parentObj => {
                parentObj.registerB |= GBEMU_0x01;
            },
            //SET 0, C
            //#0xC1:
            parentObj => {
                parentObj.registerC |= GBEMU_0x01;
            },
            //SET 0, D
            //#0xC2:
            parentObj => {
                parentObj.registerD |= GBEMU_0x01;
            },
            //SET 0, E
            //#0xC3:
            parentObj => {
                parentObj.registerE |= GBEMU_0x01;
            },
            //SET 0, H
            //#0xC4:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x0100;
            },
            //SET 0, L
            //#0xC5:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x01;
            },
            //SET 0, (HL)
            //#0xC6:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x01);
            },
            //SET 0, A
            //#0xC7:
            parentObj => {
                parentObj.registerA |= GBEMU_0x01;
            },
            //SET 1, B
            //#0xC8:
            parentObj => {
                parentObj.registerB |= GBEMU_0x02;
            },
            //SET 1, C
            //#0xC9:
            parentObj => {
                parentObj.registerC |= GBEMU_0x02;
            },
            //SET 1, D
            //#0xCA:
            parentObj => {
                parentObj.registerD |= GBEMU_0x02;
            },
            //SET 1, E
            //#0xCB:
            parentObj => {
                parentObj.registerE |= GBEMU_0x02;
            },
            //SET 1, H
            //#0xCC:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x0200;
            },
            //SET 1, L
            //#0xCD:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x02;
            },
            //SET 1, (HL)
            //#0xCE:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x02);
            },
            //SET 1, A
            //#0xCF:
            parentObj => {
                parentObj.registerA |= GBEMU_0x02;
            },
            //SET GBEMU_2, B
            //#0xD0:
            parentObj => {
                parentObj.registerB |= GBEMU_0x04;
            },
            //SET GBEMU_2, C
            //#0xD1:
            parentObj => {
                parentObj.registerC |= GBEMU_0x04;
            },
            //SET GBEMU_2, D
            //#0xD2:
            parentObj => {
                parentObj.registerD |= GBEMU_0x04;
            },
            //SET GBEMU_2, E
            //#0xD3:
            parentObj => {
                parentObj.registerE |= GBEMU_0x04;
            },
            //SET GBEMU_2, H
            //#0xD4:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x0400;
            },
            //SET GBEMU_2, L
            //#0xD5:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x04;
            },
            //SET GBEMU_2, (HL)
            //#0xD6:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x04);
            },
            //SET GBEMU_2, A
            //#0xD7:
            parentObj => {
                parentObj.registerA |= GBEMU_0x04;
            },
            //SET GBEMU_3, B
            //#0xD8:
            parentObj => {
                parentObj.registerB |= GBEMU_0x08;
            },
            //SET GBEMU_3, C
            //#0xD9:
            parentObj => {
                parentObj.registerC |= GBEMU_0x08;
            },
            //SET GBEMU_3, D
            //#0xDA:
            parentObj => {
                parentObj.registerD |= GBEMU_0x08;
            },
            //SET GBEMU_3, E
            //#0xDB:
            parentObj => {
                parentObj.registerE |= GBEMU_0x08;
            },
            //SET GBEMU_3, H
            //#0xDC:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x0800;
            },
            //SET GBEMU_3, L
            //#0xDD:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x08;
            },
            //SET GBEMU_3, (HL)
            //#0xDE:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x08);
            },
            //SET GBEMU_3, A
            //#0xDF:
            parentObj => {
                parentObj.registerA |= GBEMU_0x08;
            },
            //SET GBEMU_4, B
            //#0xE0:
            parentObj => {
                parentObj.registerB |= GBEMU_0x10;
            },
            //SET GBEMU_4, C
            //#0xE1:
            parentObj => {
                parentObj.registerC |= GBEMU_0x10;
            },
            //SET GBEMU_4, D
            //#0xE2:
            parentObj => {
                parentObj.registerD |= GBEMU_0x10;
            },
            //SET GBEMU_4, E
            //#0xE3:
            parentObj => {
                parentObj.registerE |= GBEMU_0x10;
            },
            //SET GBEMU_4, H
            //#0xE4:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x1000;
            },
            //SET GBEMU_4, L
            //#0xE5:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x10;
            },
            //SET GBEMU_4, (HL)
            //#0xE6:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x10);
            },
            //SET GBEMU_4, A
            //#0xE7:
            parentObj => {
                parentObj.registerA |= GBEMU_0x10;
            },
            //SET GBEMU_5, B
            //#0xE8:
            parentObj => {
                parentObj.registerB |= GBEMU_0x20;
            },
            //SET GBEMU_5, C
            //#0xE9:
            parentObj => {
                parentObj.registerC |= GBEMU_0x20;
            },
            //SET GBEMU_5, D
            //#0xEA:
            parentObj => {
                parentObj.registerD |= GBEMU_0x20;
            },
            //SET GBEMU_5, E
            //#0xEB:
            parentObj => {
                parentObj.registerE |= GBEMU_0x20;
            },
            //SET GBEMU_5, H
            //#0xEC:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x2000;
            },
            //SET GBEMU_5, L
            //#0xED:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x20;
            },
            //SET GBEMU_5, (HL)
            //#0xEE:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x20);
            },
            //SET GBEMU_5, A
            //#0xEF:
            parentObj => {
                parentObj.registerA |= GBEMU_0x20;
            },
            //SET GBEMU_6, B
            //#0xF0:
            parentObj => {
                parentObj.registerB |= GBEMU_0x40;
            },
            //SET GBEMU_6, C
            //#0xF1:
            parentObj => {
                parentObj.registerC |= GBEMU_0x40;
            },
            //SET GBEMU_6, D
            //#0xF2:
            parentObj => {
                parentObj.registerD |= GBEMU_0x40;
            },
            //SET GBEMU_6, E
            //#0xF3:
            parentObj => {
                parentObj.registerE |= GBEMU_0x40;
            },
            //SET GBEMU_6, H
            //#0xF4:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x4000;
            },
            //SET GBEMU_6, L
            //#0xF5:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x40;
            },
            //SET GBEMU_6, (HL)
            //#0xF6:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x40);
            },
            //SET GBEMU_6, A
            //#0xF7:
            parentObj => {
                parentObj.registerA |= GBEMU_0x40;
            },
            //SET GBEMU_7, B
            //#0xF8:
            parentObj => {
                parentObj.registerB |= GBEMU_0x80;
            },
            //SET GBEMU_7, C
            //#0xF9:
            parentObj => {
                parentObj.registerC |= GBEMU_0x80;
            },
            //SET GBEMU_7, D
            //#0xFA:
            parentObj => {
                parentObj.registerD |= GBEMU_0x80;
            },
            //SET GBEMU_7, E
            //#0xFB:
            parentObj => {
                parentObj.registerE |= GBEMU_0x80;
            },
            //SET GBEMU_7, H
            //#0xFC:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x8000;
            },
            //SET GBEMU_7, L
            //#0xFD:
            parentObj => {
                parentObj.registersHL |= GBEMU_0x80;
            },
            //SET GBEMU_7, (HL)
            //#0xFE:
            parentObj => {
                parentObj.memoryWriter[parentObj.registersHL](parentObj, parentObj.registersHL, parentObj.memoryReader[parentObj.registersHL](parentObj, parentObj.registersHL) | GBEMU_0x80);
            },
            //SET GBEMU_7, A
            //#0xFF:
            parentObj => {
                parentObj.registerA |= GBEMU_0x80;
            }
        ];
        this.tickTable = [
            //Number of machine cycles for each instruction:
            GBEMU_4, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_20, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //0
            GBEMU_4, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //1
            GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //2
            GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_12, GBEMU_12, GBEMU_4, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //3
            GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //4
            GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //5
            GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //6
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //7
            GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //8
            GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //9
            GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //A
            GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_4, //B
            GBEMU_8, GBEMU_12, GBEMU_12, GBEMU_16, GBEMU_12, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_12, 0, GBEMU_12, GBEMU_24, GBEMU_8, GBEMU_16, //C
            GBEMU_8, GBEMU_12, GBEMU_12, GBEMU_4, GBEMU_12, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_12, GBEMU_4, GBEMU_12, GBEMU_4, GBEMU_8, GBEMU_16, //D
            GBEMU_12, GBEMU_12, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_16, GBEMU_4, GBEMU_16, GBEMU_4, GBEMU_4, GBEMU_4, GBEMU_8, GBEMU_16, //E
            GBEMU_12, GBEMU_12, GBEMU_8, GBEMU_4, GBEMU_4, GBEMU_16, GBEMU_8, GBEMU_16, GBEMU_12, GBEMU_8, GBEMU_16, GBEMU_4, 0, GBEMU_4, GBEMU_8, GBEMU_16 //F
        ];
        this.secondaryTickTable = [
            //Number of machine cycles for each 0xCBXX instruction:
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //0
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //1
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //2
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //3
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, //4
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, //5
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, //6
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_12, GBEMU_8, //7
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //8
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //9
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //A
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //B
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //C
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //D
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, //E
            GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_8, GBEMU_16, GBEMU_8 //F
        ];
        this.canvas = canvas; //Canvas DOM object for drawing out the graphics to.
        this.romImage = romImage;
        this.updateGBBGPalette = this.updateGBColorizedBGPalette;
        this.updateGBOBJPalette = this.updateGBRegularOBJPalette;
        //Compile the LCD controller functions.
        this.initializeLCDController();
        this.initializeAudioStartState();
        this.initializeTiming();
        //Initialize the white noise cache tables ahead of time:
        this.intializeWhiteNoise();
    }
    returnFromRTCState() {
        //debugLog('This is returnFromRTCState');
        if (typeof this.openRTC === 'function' && this.cTimeR) {
            let rtcData = this.openRTC(this.name);
            let index = 0;
            this.lastIteration = rtcData[index++];
            this.rtcIsLatched = rtcData[index++];
            this.latchedSeconds = rtcData[index++];
            this.latchedMinutes = rtcData[index++];
            this.latchedHours = rtcData[index++];
            this.latchedLDays = rtcData[index++];
            this.latchedHDays = rtcData[index++];
            this.rtcSeconds = rtcData[index++];
            this.rtcMinutes = rtcData[index++];
            this.rtcHours = rtcData[index++];
            this.rtcDays = rtcData[index++];
            this.rtcDayOverFlow = rtcData[index++];
            this.rtcHalt = rtcData[index];
        }
    }
    start() {
        //debugLog('This is GameBoyCore-start');
        this.initMemory(); //Write the startup memory.
        this.romLoad(); //Load the rom into memory and get cartridge information from it.
        this.initLCD(); //Initialize the graphics.
        this.initSound(); //Sound object initialization.
        this.run(); //Start the emulation.
    }
    initMemory() {
        //debugLog('This is initMemory');
        //Initialize the RAM:
        this.memory = this.getTypedArray(GBEMU_0x10000, 0, 'uint8');
        this.frameBuffer = this.getTypedArray(GBEMU_23040, GBEMU_0xF8F8F8, 'int32');
        this.bgCHRBank1.array = this.getTypedArray(GBEMU_0x800, 0, 'uint8');
        this.tickTable = this.toTypedArray(this.tickTable, 'uint8');
        this.secondaryTickTable = this.toTypedArray(this.secondaryTickTable, 'uint8');
        this.channel3PCM = this.getTypedArray(GBEMU_0x20, 0, 'int8');
    }
    generateCacheArray(tileAmount) {
        //debugLog('This is generateCacheArray');
        let tileArray = [];
        let tileNumber = 0;
        while (tileNumber < tileAmount) {
            let object = new ArrayObject();
            object.array = this.getTypedArray(GBEMU_64, 0, 'uint8');
            tileArray[tileNumber] = object;
            tileNumber += 1;
        }
        return tileArray;
    }
    initSkipBootstrap() {
        //debugLog('This is initSkipBootstrap');
        let index = GBEMU_0xFF;
        while (index >= 0) {
            if (index >= GBEMU_0x30 && index < GBEMU_0x40) {
                this.memoryWrite(GBEMU_0xFF00 | index, this.ffxxDump[index]);
            }
            else {
                switch (index) {
                    case GBEMU_0x00:
                    case GBEMU_0x01:
                    case GBEMU_0x02:
                    case GBEMU_0x05:
                    case GBEMU_0x07:
                    case GBEMU_0x0F:
                    case GBEMU_0xFF:
                        this.memoryWrite(GBEMU_0xFF00 | index, this.ffxxDump[index]);
                        break;
                    default:
                        this.memory[GBEMU_0xFF00 | index] = this.ffxxDump[index];
                }
            }
            index -= 1;
        }
        if (this.cGBC) {
            this.memory[GBEMU_0xFF6C] = GBEMU_0xFE;
            this.memory[GBEMU_0xFF74] = GBEMU_0xFE;
        }
        else {
            this.memory[GBEMU_0xFF48] = GBEMU_0xFF;
            this.memory[GBEMU_0xFF49] = GBEMU_0xFF;
            this.memory[GBEMU_0xFF6C] = GBEMU_0xFF;
            this.memory[GBEMU_0xFF74] = GBEMU_0xFF;
        }
        cout('Starting without the GBC boot rom.', 0);
        this.registerA = this.cGBC ? GBEMU_0x11 : GBEMU_0x1;
        this.registerB = 0;
        this.registerC = GBEMU_0x13;
        this.registerD = 0;
        this.registerE = GBEMU_0xD8;
        this.fZero = true;
        this.fSubtract = false;
        this.fHalfCarry = true;
        this.fCarry = true;
        this.registersHL = GBEMU_0x014D;
        this.lcdControl = this.lineControl;
        this.ime = false;
        this.irqLineMatched = 0;
        this.interruptsRequested = GBEMU_225;
        this.interruptsEnabled = 0;
        this.hdmaRunning = false;
        this.cpuTicks = GBEMU_12;
        this.statTracker = 0;
        this.modeSTAT = 1;
        this.spriteCount = GBEMU_252;
        this.lycMatchTriggerSTAT = false;
        this.mode2TriggerSTAT = false;
        this.mode1TriggerSTAT = false;
        this.mode0TriggerSTAT = false;
        this.lcdIsOn = true;
        this.channel1FrequencyTracker = GBEMU_0x2000;
        this.channel1DutyTracker = 0;
        this.channel1CachedDuty = this.dutyLookup[GBEMU_2];
        this.channel1totalLength = 0;
        this.channel1envelopeVolume = GBEMU_0;
        this.channel1envelopeType = false;
        this.channel1envelopeSweeps = 0;
        this.channel1envelopeSweepsLast = GBEMU_0;
        this.channel1consecutive = true;
        this.channel1frequency = GBEMU_1985;
        this.channel1SweepFault = true;
        this.channel1ShadowFrequency = GBEMU_1985;
        this.channel1timeSweep = 1;
        this.channel1lastTimeSweep = 0;
        this.channel1numSweep = GBEMU_0;
        this.channel1frequencySweepDivider = 0;
        this.channel1decreaseSweep = false;
        this.channel2FrequencyTracker = GBEMU_0x2000;
        this.channel2DutyTracker = 0;
        this.channel2CachedDuty = this.dutyLookup[GBEMU_2];
        this.channel2totalLength = 0;
        this.channel2envelopeVolume = GBEMU_0;
        this.channel2envelopeType = false;
        this.channel2envelopeSweeps = 0;
        this.channel2envelopeSweepsLast = 0;
        this.channel2consecutive = true;
        this.channel2frequency = GBEMU_0;
        this.channel3canPlay = false;
        this.channel3totalLength = 0;
        this.channel3patternType = GBEMU_4;
        this.channel3frequency = 0;
        this.channel3consecutive = true;
        this.channel3Counter = GBEMU_0x418;
        this.channel4FrequencyPeriod = GBEMU_8;
        this.channel4totalLength = 0;
        this.channel4envelopeVolume = 0;
        this.channel4currentVolume = GBEMU_0;
        this.channel4envelopeType = false;
        this.channel4envelopeSweeps = 0;
        this.channel4envelopeSweepsLast = GBEMU_0;
        this.channel4consecutive = true;
        this.channel4BitRange = GBEMU_0x7FFF;
        this.channel4VolumeShifter = GBEMU_15;
        this.channel1FrequencyCounter = GBEMU_0x200;
        this.channel2FrequencyCounter = GBEMU_0x200;
        this.channel3Counter = GBEMU_0x800;
        this.channel3FrequencyPeriod = GBEMU_0x800;
        this.channel3lastSampleLookup = 0;
        this.channel4lastSampleLookup = GBEMU_0;
        this.vinLeftChannelMasterVolume = 1;
        this.vinRightChannelMasterVolume = 1;
        this.soundMasterEnabled = true;
        //left
        this.leftChannel1 = true;
        this.leftChannel2 = true;
        this.leftChannel3 = true;
        this.leftChannel4 = true;
        //right
        this.rightChannel1 = true;
        this.rightChannel2 = true;
        this.rightChannel3 = false;
        this.rightChannel4 = false;
        this.divTicks = GBEMU_27044;
        this.lcdTicks = GBEMU_160;
        this.timerTicks = 0;
        this.timaEnabled = false;
        this.tacClocker = GBEMU_1024;
        this.serialTimer = 0;
        this.serialShiftTimer = 0;
        this.serialShiftTimerAllocated = 0;
        this.irqEnableDelay = 0;
        this.actualScanLine = GBEMU_144;
        this.lastUnrenderedLine = GBEMU_0;
        this.gfxWindowDisplay = false;
        this.gfxSpriteShow = false;
        this.gfxSpriteNormalHeight = true;
        this.bgEnabled = true;
        this.bgPriorityEnabled = true;
        this.gfxWindowCHRBankPosition = GBEMU_0;
        this.gfxBackgroundCHRBankPosition = 0;
        this.gfxBackgroundBankOffset = 0;
        this.windowY = GBEMU_0;
        this.windowX = 0;
        this.drewBlank = GBEMU_0;
        this.midScanlineOffset = -1;
        this.currentX = GBEMU_0;
    }
    initBootstrap() {
        //debugLog('This is initBootstrap')
        //Start as an unset device:
        cout('Starting the selected boot rom.', 0);
        this.programCounter = 0;
        this.stackPointer = 0;
        this.ime = false;
        this.lcdTicks = GBEMU_0;
        this.divTicks = 0;
        this.registerA = GBEMU_0;
        this.registerB = 0;
        this.registerC = GBEMU_0;
        this.registerD = 0;
        this.registerE = GBEMU_0;
        this.fZero = false;
        this.fSubtract = false;
        this.fHalfCarry = false;
        this.fCarry = false;
        this.registersHL = GBEMU_0;
        //left
        this.leftChannel1 = false;
        this.leftChannel2 = false;
        this.leftChannel3 = false;
        this.leftChannel4 = false;
        //right
        this.rightChannel1 = false;
        this.rightChannel2 = false;
        this.rightChannel3 = false;
        this.rightChannel4 = false;
        this.channel2frequency = GBEMU_0;
        this.channel1frequency = GBEMU_0;
        this.channel4consecutive = false;
        this.channel2consecutive = false;
        this.channel1consecutive = false;
        this.vinLeftChannelMasterVolume = GBEMU_8;
        this.vinRightChannelMasterVolume = GBEMU_8;
        this.memory[GBEMU_0xFF00] = GBEMU_0xF; //Set the joypad state.
    }
    romLoad() {
        //debugLog('This is romLoad');
        //Load the first two rom banks (0x0000 - 0x7FFF) into regular gameboy memory:
        this.rom = [];
        this.usedBootrom = settings[1];
        let maxLength = this.romImage.length;
        if (maxLength < GBEMU_0x4000) {
            return;
        }
        this.rom = this.getTypedArray(maxLength, 0, 'uint8');
        let romIndex = 0;
        if (this.usedBootrom) {
            if (!settings[GBEMU_11]) {
                //Patch in the GBC boot rom into the memory map:
                while (romIndex < GBEMU_0x100) {
                    this.memory[romIndex] = this.gbCBOOTrom[romIndex]; //Load in the GameBoy Color BOOT rom.
                    this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Decode the rom binary for the switch out.
                    romIndex += 1;
                }
                while (romIndex < GBEMU_0x200) {
                    this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Load in the game rom.
                    this.memory[romIndex] = this.rom[romIndex];
                    romIndex += 1;
                }
                while (romIndex < GBEMU_0x900) {
                    this.memory[romIndex] = this.gbCBOOTrom[romIndex - GBEMU_0x100]; //Load in the GameBoy Color BOOT rom.
                    this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Decode the rom binary for the switch out.
                    romIndex += 1;
                }
                this.usedGBCBootrom = true;
            }
            else {
                //Patch in the GBC boot rom into the memory map:
                while (romIndex < GBEMU_0x100) {
                    this.memory[romIndex] = this.gbBOOTrom[romIndex]; //Load in the GameBoy Color BOOT rom.
                    this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Decode the rom binary for the switch out.
                    romIndex += 1;
                }
            }
            while (romIndex < GBEMU_0x4000) {
                this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Load in the game rom.
                this.memory[romIndex] = this.rom[romIndex];
                romIndex += 1;
            }
        }
        else {
            //Don't load in the boot rom:
            while (romIndex < GBEMU_0x4000) {
                this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF; //Load in the game rom.
                this.memory[romIndex] = this.rom[romIndex];
                romIndex += 1;
            }
        }
        //Finish the decoding of the rom binary:
        while (romIndex < maxLength) {
            this.rom[romIndex] = this.romImage.charCodeAt(romIndex) & GBEMU_0xFF;
            romIndex += 1;
        }
        this.romBankEdge = Math.floor(this.rom.length / GBEMU_0x4000);
        //Set up the emulator for the cartidge specifics:
        this.interpretCartridge();
        //Check for IRQ matching upon initialization:
        this.checkIRQMatching();
    }
    getromImage() {
        //Return the binary version of the rom image currently running:
        if (this.romImage.length > 0) {
            return this.romImage.length;
        }
        let length = this.rom.length;
        for (let index = 0; index < length; index++) {
            this.romImage += String.fromCharCode(this.rom[index]);
        }
        return this.romImage;
    }
    interpretCartridge() {
        //debugLog('This is interpretCartridge');
        // rom name
        for (let index = GBEMU_0x134; index < GBEMU_0x13F; index++) {
            if (this.romImage.charCodeAt(index) > 0) {
                this.name += this.romImage[index];
            }
        }
        // rom game code (for newer games)
        for (let index = GBEMU_0x13F; index < GBEMU_0x143; index++) {
            if (this.romImage.charCodeAt(index) > 0) {
                this.gameCode += this.romImage[index];
            }
        }
        cout('Game Code: ' + this.gameCode, 0);
        // Cartridge type
        this.cartridgeType = this.rom[GBEMU_0x147];
        cout('Cartridge type #' + this.cartridgeType, 0);
        //Map out rom cartridge sub-types.
        let mbcType = '';
        switch (this.cartridgeType) {
            case GBEMU_0x00:
                //rom w/o bank switching
                if (!settings[GBEMU_9]) {
                    mbcType = 'rom';
                    break;
                }
            case GBEMU_0x01:
                this.cMBC1 = true;
                mbcType = 'MBC1';
                break;
            case GBEMU_0x02:
                this.cMBC1 = true;
                this.cSRAM = true;
                mbcType = 'MBC1 + SRAM';
                break;
            case GBEMU_0x03:
                this.cMBC1 = true;
                this.cSRAM = true;
                this.cBATT = true;
                mbcType = 'MBC1 + SRAM + BATT';
                break;
            case GBEMU_0x05:
                this.cMBC2 = true;
                mbcType = 'MBC2';
                break;
            case GBEMU_0x06:
                this.cMBC2 = true;
                this.cBATT = true;
                mbcType = 'MBC2 + BATT';
                break;
            case GBEMU_0x08:
                this.cSRAM = true;
                mbcType = 'rom + SRAM';
                break;
            case GBEMU_0x09:
                this.cSRAM = true;
                this.cBATT = true;
                mbcType = 'rom + SRAM + BATT';
                break;
            case GBEMU_0x0B:
                this.cMMMO1 = true;
                mbcType = 'MMMO1';
                break;
            case GBEMU_0x0C:
                this.cMMMO1 = true;
                this.cSRAM = true;
                mbcType = 'MMMO1 + SRAM';
                break;
            case GBEMU_0x0D:
                this.cMMMO1 = true;
                this.cSRAM = true;
                this.cBATT = true;
                mbcType = 'MMMO1 + SRAM + BATT';
                break;
            case GBEMU_0x0F:
                this.cMBC3 = true;
                this.cTimeR = true;
                this.cBATT = true;
                mbcType = 'MBC3 + TimeR + BATT';
                break;
            case GBEMU_0x10:
                this.cMBC3 = true;
                this.cTimeR = true;
                this.cBATT = true;
                this.cSRAM = true;
                mbcType = 'MBC3 + TimeR + BATT + SRAM';
                break;
            case GBEMU_0x11:
                this.cMBC3 = true;
                mbcType = 'MBC3';
                break;
            case GBEMU_0x12:
                this.cMBC3 = true;
                this.cSRAM = true;
                mbcType = 'MBC3 + SRAM';
                break;
            case GBEMU_0x13:
                this.cMBC3 = true;
                this.cSRAM = true;
                this.cBATT = true;
                mbcType = 'MBC3 + SRAM + BATT';
                break;
            case GBEMU_0x19:
                this.cMBC5 = true;
                mbcType = 'MBC5';
                break;
            case GBEMU_0x1A:
                this.cMBC5 = true;
                this.cSRAM = true;
                mbcType = 'MBC5 + SRAM';
                break;
            case GBEMU_0x1B:
                this.cMBC5 = true;
                this.cSRAM = true;
                this.cBATT = true;
                mbcType = 'MBC5 + SRAM + BATT';
                break;
            case GBEMU_0x1C:
                this.cRUMBLE = true;
                mbcType = 'RUMBLE';
                break;
            case GBEMU_0x1D:
                this.cRUMBLE = true;
                this.cSRAM = true;
                mbcType = 'RUMBLE + SRAM';
                break;
            case GBEMU_0x1E:
                this.cRUMBLE = true;
                this.cSRAM = true;
                this.cBATT = true;
                mbcType = 'RUMBLE + SRAM + BATT';
                break;
            case GBEMU_0x1F:
                this.cCamera = true;
                mbcType = 'GameBoy Camera';
                break;
            case GBEMU_0x22:
                this.cMBC7 = true;
                this.cSRAM = true;
                this.cBATT = true;
                mbcType = 'MBC7 + SRAM + BATT';
                break;
            case GBEMU_0xFD:
                this.cTAMA5 = true;
                mbcType = 'TAMA5';
                break;
            case GBEMU_0xFE:
                this.cHuC3 = true;
                mbcType = 'HuC3';
                break;
            case GBEMU_0xFF:
                this.cHuC1 = true;
                mbcType = 'HuC1';
                break;
            default:
                mbcType = 'Unknown';
                cout('Cartridge type is unknown.', GBEMU_2);
                pausePlay();
        }
        cout('Cartridge Type: ' + mbcType + '.', 0);
        // rom and RAM banks
        this.numRomBanks = this.romBanks.get(this.rom[GBEMU_0x148]);
        cout(this.numRomBanks + ' rom banks.', 0);
        switch (this.ramBanks[this.rom[GBEMU_0x149]]) {
            case 0:
                cout('No RAM banking requested for allocation or MBC is of type GBEMU_2.', 0);
                break;
            case GBEMU_2:
                cout('1 RAM bank requested for allocation.', 0);
                break;
            case GBEMU_3:
                cout('GBEMU_4 RAM banks requested for allocation.', 0);
                break;
            case GBEMU_4:
                cout('GBEMU_16 RAM banks requested for allocation.', 0);
                break;
            default:
                cout('RAM bank amount requested is unknown, will use maximum allowed by specified MBC type.', 0);
        }
        //Check the GB/GBC mode byte:
        if (!this.usedBootrom) {
            switch (this.rom[GBEMU_0x143]) {
                case GBEMU_0x00: //Only GB mode
                    this.cGBC = false;
                    cout('Only GB mode detected.', 0);
                    break;
                case GBEMU_0x32: //Exception to the GBC identifying code:
                    if (!settings[GBEMU_2] && this.name + this.gameCode + this.rom[GBEMU_0x143] === 'Game and Watch GBEMU_50') {
                        this.cGBC = true;
                        cout('Created a boot exception for Game and Watch Gallery GBEMU_2 (GBC ID byte is wrong on the cartridge).', 1);
                    }
                    else {
                        this.cGBC = false;
                    }
                    break;
                case GBEMU_0x80: //Both GB + GBC modes
                    this.cGBC = !settings[GBEMU_2];
                    cout('GB and GBC mode detected.', 0);
                    break;
                case GBEMU_0xC0: //Only GBC mode
                    this.cGBC = true;
                    cout('Only GBC mode detected.', 0);
                    break;
                default:
                    this.cGBC = false;
                    cout('Unknown GameBoy game type code #' + this.rom[GBEMU_0x143] + ', defaulting to GB mode (Old games dont have a type code).', 1);
            }
            this.inBootstrap = false;
            //CPU/(V)RAM initialization.
            this.setupRAM();
            this.initSkipBootstrap();
            // Line added for benchmarking.
            this.initializeAudioStartState();
        }
        else {
            // AAllow the GBC boot ROM to run in GBC mode...
            this.cGBC = this.usedGBCBootrom;
            //CPU/(V)RAM initialization.
            this.setupRAM();
            this.initBootstrap();
        }
        this.initializeModeSpecificArrays();
        let cOldLicense = this.rom[GBEMU_0x14B];
        let cNewLicense = (this.rom[GBEMU_0x144] & GBEMU_0xFF00) | (this.rom[GBEMU_0x145] & GBEMU_0xFF);
        if (cOldLicense !== GBEMU_0x33) {
            //Old Style License Header
            cout('Old style license code: ' + cOldLicense, 0);
        }
        else {
            //New Style License Header
            cout('New style license code: ' + cNewLicense, 0);
        }
        this.romImage = ''; //Memory consumption reduction.
    }
    disableBootrom() {
        //debugLog('This is disableBootrom');
        //Remove any traces of the boot rom from rom memory.
        for (let index = 0; index < GBEMU_0x100; ++index) {
            this.memory[index] = this.rom[index]; //Replace the GameBoy or GameBoy Color boot rom with the game rom.
        }
        if (this.usedGBCBootrom) {
            //Remove any traces of the boot rom from rom memory.
            for (let index = GBEMU_0x200; index < GBEMU_0x900; ++index) {
                this.memory[index] = this.rom[index]; //Replace the GameBoy Color boot rom with the game rom.
            }
            if (!this.cGBC) {
                //Clean up the post-boot (GB mode only) state:
                this.gBCtoGBModeAdjust();
            }
            else {
                this.recompileBootIOWriteHandling();
            }
        }
        else {
            this.recompileBootIOWriteHandling();
        }
    }
    initializeTiming() {
        //debugLog('This is initializeTiming');
        //Emulator Timing:
        this.baseCPUCyclesPerIteration = (GBEMU_0x80000 / GBEMU_0x7D) * settings[GBEMU_6];
        this.cpuCyclesTotalRoundoff = this.baseCPUCyclesPerIteration % GBEMU_4;
        this.cpuCyclesTotal = (this.baseCPUCyclesPerIteration - this.cpuCyclesTotalRoundoff) | 0;
        this.cpuCyclesTotalBase = this.cpuCyclesTotal;
        this.cpuCyclesTotalCurrent = 0;
    }
    setupRAM() {
        //debugLog('This is setupRAM');
        //Setup the auxilliary/switchable RAM:
        if (this.cMBC2) {
            this.numRamBanks = 1 / GBEMU_16;
        }
        else if (this.cMBC1 || this.cRUMBLE || this.cMBC3 || this.cHuC3) {
            this.numRamBanks = GBEMU_4;
        }
        else if (this.cMBC5) {
            this.numRamBanks = GBEMU_16;
        }
        else if (this.cSRAM) {
            this.numRamBanks = 1;
        }
        if (this.numRamBanks > 0) {
            if (!this.mBCRAMUtilized()) {
                //For rom and unknown MBC cartridges using the external RAM:
                this.mbcRamBanksEnabled = true;
            }
            //Switched RAM Used
            let mbcRam = typeof this.openMBC === 'function' ? this.openMBC(this.name) : [];
            if (mbcRam.length > 0) {
                //Flash the SRAM into memory:
                this.mbcRam = this.toTypedArray(mbcRam, 'uint8');
            }
            else {
                this.mbcRam = this.getTypedArray(this.numRamBanks * GBEMU_0x2000, 0, 'uint8');
            }
        }
        cout('Actual bytes of MBC RAM allocated: ' + this.numRamBanks * GBEMU_0x2000, 0);
        this.returnFromRTCState();
        //Setup the RAM for GBC mode.
        if (this.cGBC) {
            this.vram = this.getTypedArray(GBEMU_0x2000, 0, 'uint8');
            this.gbcMemory = this.getTypedArray(GBEMU_0x7000, 0, 'uint8');
        }
        this.memoryReadJumpCompile();
        this.memoryWriteJumpCompile();
    }
    mBCRAMUtilized() {
        //debugLog('This is MBCRAMUtilized');
        return this.cMBC1 || this.cMBC2 || this.cMBC3 || this.cMBC5 || this.cMBC7 || this.cRUMBLE;
    }
    recomputeDimension() {
        //debugLog('This is recomputeDimension');
        initNewCanvas();
        //Cache some dimension info:
        this.onscreenWidth = this.canvas.width;
        this.onscreenHeight = this.canvas.height;
        // The following line was modified for benchmarking:
        if (gameBoyWindow.mozRequestAnimationFrame) {
            //Firefox slowness hack:
            this.onscreenWidth = !settings[GBEMU_12] ? GBEMU_160 : this.canvas.width;
            this.canvas.width = this.onscreenWidth;
            this.onscreenHeight = !settings[GBEMU_12] ? GBEMU_144 : this.canvas.height;
            this.canvas.height = this.onscreenHeight;
        }
        else {
            this.onscreenWidth = this.canvas.width;
            this.onscreenHeight = this.canvas.height;
        }
        this.offscreenWidth = !settings[GBEMU_12] ? GBEMU_160 : this.canvas.width;
        this.offscreenHeight = !settings[GBEMU_12] ? GBEMU_144 : this.canvas.height;
        this.offscreenRGBCount = this.offscreenWidth * this.offscreenHeight * GBEMU_4;
    }
    initLCD() {
        //debugLog('This is initLCD');
        this.recomputeDimension();
        if (this.offscreenRGBCount !== GBEMU_92160) {
            //Only create the resizer handle if we need it:
            this.compileResizeFrameBufferFunction();
        }
        else {
            //Resizer not needed:
            this.resizer = null;
        }
        this.canvasOffscreen = new GameBoyCanvas(); // Line modified for benchmarking.
        this.canvasOffscreen.width = this.offscreenWidth;
        this.canvasOffscreen.height = this.offscreenHeight;
        this.drawContextOffscreen = this.canvasOffscreen.getContext('2d');
        this.drawContextOnscreen = this.canvas.getContext('2d');
        //Get a CanvasPixelArray buffer:
        this.canvasBuffer = this.drawContextOffscreen.createImageData(this.offscreenWidth, this.offscreenHeight);
        let index = this.offscreenRGBCount;
        while (index > 0) {
            index -= GBEMU_4;
            this.canvasBuffer.data[index] = GBEMU_0xF8;
            this.canvasBuffer.data[index + 1] = GBEMU_0xF8;
            this.canvasBuffer.data[index + GBEMU_2] = GBEMU_0xF8;
            this.canvasBuffer.data[index + GBEMU_3] = GBEMU_0xFF;
        }
        this.graphicsBlit();
        this.canvas.style.visibility = 'visible';
        if (this.swizzledFrame === null || this.swizzledFrame.length === 0) {
            this.swizzledFrame = this.getTypedArray(GBEMU_69120, GBEMU_0xFF, 'uint8');
        }
        //Test the draw system and browser vblank latching:
        this.drewFrame = true; //Copy the latest graphics to buffer.
        this.requestDraw();
    }
    graphicsBlit() {
        //debugLog('This is graphicsBlit');
        if (this.offscreenWidth === this.onscreenWidth && this.offscreenHeight === this.onscreenHeight) {
            this.drawContextOnscreen.putImageData(this.canvasBuffer, 0, 0);
        }
        else {
            this.drawContextOffscreen.putImageData(this.canvasBuffer, 0, 0);
            this.drawContextOnscreen.drawImage(this.canvasOffscreen, 0, 0, this.onscreenWidth, this.onscreenHeight);
        }
    }
    joyPadEvent(key, down) {
        if (down) {
            this.joyPad &= GBEMU_0xFF ^ (1 << key);
            if (!this.cGBC && (!this.usedBootrom || !this.usedGBCBootrom)) {
                this.interruptsRequested |= GBEMU_0x10; //A real GBC doesn't set this!
                this.remainingClocks = 0;
                this.checkIRQMatching();
            }
        }
        else {
            this.joyPad |= 1 << key;
        }
        this.memory[GBEMU_0xFF00] =
            (this.memory[GBEMU_0xFF00] & GBEMU_0x30) +
                (((this.memory[GBEMU_0xFF00] & GBEMU_0x20) === 0 ? this.joyPad >> GBEMU_4 : GBEMU_0xF) &
                    ((this.memory[GBEMU_0xFF00] & GBEMU_0x10) === 0 ? this.joyPad & GBEMU_0xF : GBEMU_0xF));
        this.cpuStopped = false;
    }
    gyroEvent(xTemp, yTemp) {
        let x = xTemp;
        let y = yTemp;
        x *= -GBEMU_100;
        x += GBEMU_2047;
        this.highX = x >> GBEMU_8;
        this.lowX = x & GBEMU_0xFF;
        y *= -GBEMU_100;
        y += GBEMU_2047;
        this.highY = y >> GBEMU_8;
        this.lowY = y & GBEMU_0xFF;
    }
    initSound() {
        //debugLog('This is initSound');
        this.sampleSize = (GBEMU_0x400000 / GBEMU_1000) * settings[GBEMU_6];
        this.machineOut = settings[GBEMU_13];
        if (settings[0]) {
            let _ = this;
            this.audioHandle = new XAudioServer(GBEMU_2, GBEMU_0x400000 / settings[GBEMU_13], 0, Math.max((this.sampleSize * settings[GBEMU_8]) / settings[GBEMU_13], GBEMU_8192) << 1, null, settings[GBEMU_14]);
            this.initAudioBuffer();
        }
        else if (this.audioHandle) {
            //Mute the audio output, as it has an immediate silencing effect:
            this.audioHandle.changeVolume(0);
        }
    }
    changeVolume() {
        if (settings[0] && this.audioHandle) {
            this.audioHandle.changeVolume(settings[GBEMU_14]);
        }
    }
    initAudioBuffer() {
        //debugLog('This is initAudioBuffer');
        this.audioIndex = 0;
        this.bufferContainAmount = Math.max((this.sampleSize * settings[GBEMU_7]) / settings[GBEMU_13], GBEMU_4096) << 1;
        this.numSamplesTotal = (this.sampleSize - (this.sampleSize % settings[GBEMU_13])) | 0;
        this.currentBuffer = this.getTypedArray(this.numSamplesTotal, GBEMU_0xF0F0, 'int32');
        this.secondaryBuffer = this.getTypedArray((this.numSamplesTotal << 1) / settings[GBEMU_13], 0, 'float32');
    }
    intializeWhiteNoise() {
        //debugLog('This is intializeWhiteNoise');
        //Noise Sample Tables:
        let randomFactor = 1;
        //GBEMU_15-bit lsfr Cache Generation:
        this.lsfr15Table = this.getTypedArray(GBEMU_0x80000, 0, 'int8');
        let lsfr = GBEMU_0x7FFF; //Seed value has all its bits set.
        let lsfrShifted = GBEMU_0x3FFF;
        for (let index = 0; index < GBEMU_0x8000; ++index) {
            //Normalize the last lsfr value for usage:
            randomFactor = 1 - (lsfr & 1); //Docs say it's the inverse.
            //Cache the different volume level results:
            this.lsfr15Table[GBEMU_0x08000 | index] = randomFactor;
            this.lsfr15Table[GBEMU_0x10000 | index] = randomFactor * GBEMU_0x2;
            this.lsfr15Table[GBEMU_0x18000 | index] = randomFactor * GBEMU_0x3;
            this.lsfr15Table[GBEMU_0x20000 | index] = randomFactor * GBEMU_0x4;
            this.lsfr15Table[GBEMU_0x28000 | index] = randomFactor * GBEMU_0x5;
            this.lsfr15Table[GBEMU_0x30000 | index] = randomFactor * GBEMU_0x6;
            this.lsfr15Table[GBEMU_0x38000 | index] = randomFactor * GBEMU_0x7;
            this.lsfr15Table[GBEMU_0x40000 | index] = randomFactor * GBEMU_0x8;
            this.lsfr15Table[GBEMU_0x48000 | index] = randomFactor * GBEMU_0x9;
            this.lsfr15Table[GBEMU_0x50000 | index] = randomFactor * GBEMU_0xA;
            this.lsfr15Table[GBEMU_0x58000 | index] = randomFactor * GBEMU_0xB;
            this.lsfr15Table[GBEMU_0x60000 | index] = randomFactor * GBEMU_0xC;
            this.lsfr15Table[GBEMU_0x68000 | index] = randomFactor * GBEMU_0xD;
            this.lsfr15Table[GBEMU_0x70000 | index] = randomFactor * GBEMU_0xE;
            this.lsfr15Table[GBEMU_0x78000 | index] = randomFactor * GBEMU_0xF;
            //Recompute the lsfr algorithm:
            lsfrShifted = lsfr >> 1;
            lsfr = lsfrShifted | (((lsfrShifted ^ lsfr) & GBEMU_0x1) << GBEMU_14);
        }
        //GBEMU_7-bit lsfr Cache Generation:
        this.lsfr7Table = this.getTypedArray(GBEMU_0x800, 0, 'int8');
        lsfr = GBEMU_0x7F; //Seed value has all its bits set.
        for (let index = 0; index < GBEMU_0x80; ++index) {
            //Normalize the last lsfr value for usage:
            randomFactor = 1 - (lsfr & 1); //Docs say it's the inverse.
            //Cache the different volume level results:
            this.lsfr7Table[GBEMU_0x080 | index] = randomFactor;
            this.lsfr7Table[GBEMU_0x100 | index] = randomFactor * GBEMU_0x2;
            this.lsfr7Table[GBEMU_0x180 | index] = randomFactor * GBEMU_0x3;
            this.lsfr7Table[GBEMU_0x200 | index] = randomFactor * GBEMU_0x4;
            this.lsfr7Table[GBEMU_0x280 | index] = randomFactor * GBEMU_0x5;
            this.lsfr7Table[GBEMU_0x300 | index] = randomFactor * GBEMU_0x6;
            this.lsfr7Table[GBEMU_0x380 | index] = randomFactor * GBEMU_0x7;
            this.lsfr7Table[GBEMU_0x400 | index] = randomFactor * GBEMU_0x8;
            this.lsfr7Table[GBEMU_0x480 | index] = randomFactor * GBEMU_0x9;
            this.lsfr7Table[GBEMU_0x500 | index] = randomFactor * GBEMU_0xA;
            this.lsfr7Table[GBEMU_0x580 | index] = randomFactor * GBEMU_0xB;
            this.lsfr7Table[GBEMU_0x600 | index] = randomFactor * GBEMU_0xC;
            this.lsfr7Table[GBEMU_0x680 | index] = randomFactor * GBEMU_0xD;
            this.lsfr7Table[GBEMU_0x700 | index] = randomFactor * GBEMU_0xE;
            this.lsfr7Table[GBEMU_0x780 | index] = randomFactor * GBEMU_0xF;
            //Recompute the lsfr algorithm:
            lsfrShifted = lsfr >> 1;
            lsfr = lsfrShifted | (((lsfrShifted ^ lsfr) & GBEMU_0x1) << GBEMU_6);
        }
        if (!this.noiseSampleTable && this.memory.length === GBEMU_0x10000) {
            //If enabling audio for the first time after a game is already running, set up the internal table reference:
            this.noiseSampleTable = (this.memory[GBEMU_0xFF22] & GBEMU_0x8) === GBEMU_0x8 ? this.lsfr7Table : this.lsfr15Table;
        }
    }
    audioUnderrunAdjustment() {
        //debugLog('This is audioUnderrunAdjustment');
        if (settings[0]) {
            let underrunAmount = this.bufferContainAmount - this.audioHandle.remainingBuffer();
            if (underrunAmount > 0) {
                this.cpuCyclesTotalCurrent += (underrunAmount >> 1) * this.machineOut;
                this.recalculateIterationClockLimit();
            }
        }
    }
    initializeAudioStartState() {
        //debugLog('This is initializeAudioStartState');
        this.channel1FrequencyTracker = GBEMU_0x2000;
        this.channel1DutyTracker = 0;
        this.channel1CachedDuty = this.dutyLookup[GBEMU_2];
        this.channel1totalLength = 0;
        this.channel1envelopeVolume = GBEMU_0;
        this.channel1envelopeType = false;
        this.channel1envelopeSweeps = GBEMU_0;
        this.channel1envelopeSweepsLast = GBEMU_0;
        this.channel1consecutive = true;
        this.channel1frequency = GBEMU_0;
        this.channel1SweepFault = false;
        this.channel1ShadowFrequency = GBEMU_0;
        this.channel1timeSweep = 1;
        this.channel1lastTimeSweep = GBEMU_0;
        this.channel1numSweep = GBEMU_0;
        this.channel1frequencySweepDivider = GBEMU_0;
        this.channel1decreaseSweep = false;
        this.channel2FrequencyTracker = GBEMU_0x2000;
        this.channel2DutyTracker = 0;
        this.channel2CachedDuty = this.dutyLookup[GBEMU_2];
        this.channel2totalLength = 0;
        this.channel2envelopeVolume = 0;
        this.channel2envelopeType = false;
        this.channel2envelopeSweeps = GBEMU_0;
        this.channel2envelopeSweepsLast = 0;
        this.channel2consecutive = true;
        this.channel2frequency = GBEMU_0;
        this.channel3canPlay = false;
        this.channel3totalLength = 0;
        this.channel3patternType = GBEMU_4;
        this.channel3frequency = 0;
        this.channel3consecutive = true;
        this.channel3Counter = GBEMU_0x800;
        this.channel4FrequencyPeriod = GBEMU_8;
        this.channel4totalLength = GBEMU_0;
        this.channel4envelopeVolume = GBEMU_0;
        this.channel4currentVolume = GBEMU_0;
        this.channel4envelopeType = false;
        this.channel4envelopeSweeps = 0;
        this.channel4envelopeSweepsLast = GBEMU_0;
        this.channel4consecutive = true;
        this.channel4BitRange = GBEMU_0x7FFF;
        this.noiseSampleTable = this.lsfr15Table;
        this.channel4VolumeShifter = GBEMU_15;
        this.channel1FrequencyCounter = GBEMU_0x2000;
        this.channel2FrequencyCounter = GBEMU_0x2000;
        this.channel3Counter = GBEMU_0x800;
        this.channel3FrequencyPeriod = GBEMU_0x800;
        this.channel3lastSampleLookup = GBEMU_0;
        this.channel4lastSampleLookup = 0;
        this.vinLeftChannelMasterVolume = GBEMU_8;
        this.vinRightChannelMasterVolume = GBEMU_8;
        this.mixerOutputCache = 0;
        this.sequencerClocks = GBEMU_0x2000;
        this.sequencePosition = 0;
        this.channel4FrequencyPeriod = GBEMU_8;
        this.channel4Counter = GBEMU_8;
        this.cachedChannel3Sample = 0;
        this.cachedChannel4Sample = 0;
        //default is false
        this.channel1Enabled = false;
        this.channel2Enabled = false;
        this.channel3Enabled = false;
        this.channel4Enabled = false;
        //default is false
        this.channel1canPlay = false;
        this.channel2canPlay = false;
        this.channel4canPlay = false;
        //cahce
        this.channel1OutputLevelCache();
        this.channel2OutputLevelCache();
        this.channel3OutputLevelCache();
        this.channel4OutputLevelCache();
    }
    outputAudio() {
        //debugLog('This is outputAudio');
        let sampleFactor = 0;
        let dirtySample = 0;
        let averageL = 0;
        let averageR = 0;
        let destinationPosition = 0;
        let divisor1 = settings[GBEMU_13];
        let divisor2 = divisor1 * GBEMU_0xF0;
        let sourcePosition = 0;
        while (sourcePosition < this.numSamplesTotal) {
            sampleFactor = 0;
            averageL = 0;
            averageR = 0;
            while (sampleFactor < divisor1) {
                dirtySample = this.currentBuffer[sourcePosition++];
                averageL += dirtySample >> GBEMU_9;
                averageR += dirtySample & GBEMU_0x1FF;
                sampleFactor += 1;
            }
            this.secondaryBuffer[destinationPosition++] = averageL / divisor2 - 1;
            this.secondaryBuffer[destinationPosition++] = averageR / divisor2 - 1;
        }
        this.audioHandle.writeAudioNoCallback(this.secondaryBuffer);
    }
    //Below are the audio generation functions timed against the CPU:
    generateAudio(numSamplesTemp) {
        //debugLog('This is generateAudio');
        let numSamples = numSamplesTemp;
        if (this.soundMasterEnabled && !this.cpuStopped) {
            let samplesToGenerate = 0;
            while (numSamples > 0) {
                samplesToGenerate = numSamples < this.sequencerClocks ? numSamples : this.sequencerClocks;
                this.sequencerClocks -= samplesToGenerate;
                numSamples -= samplesToGenerate;
                samplesToGenerate -= 1;
                while (samplesToGenerate > -1) {
                    this.computeAudioChannels();
                    this.currentBuffer[this.audioIndex++] = this.mixerOutputCache;
                    if (this.audioIndex === this.numSamplesTotal) {
                        this.audioIndex = 0;
                        this.outputAudio();
                    }
                    samplesToGenerate -= 1;
                }
                if (this.sequencerClocks === 0) {
                    this.audioComputeSequencer();
                    this.sequencerClocks = GBEMU_0x2000;
                }
            }
        }
        else {
            //SILENT OUTPUT:
            numSamples -= 1;
            while (numSamples > -1) {
                numSamples -= 1;
                this.currentBuffer[this.audioIndex++] = GBEMU_0xF0F0;
                if (this.audioIndex === this.numSamplesTotal) {
                    this.audioIndex = 0;
                    this.outputAudio();
                }
            }
        }
    }
    //Generate audio, but don't actually output it (Used for when sound is disabled by user/browser):
    generateAudioFake(numSamplesTemp) {
        //debugLog('This is generateAudioFake');
        if (this.soundMasterEnabled && !this.cpuStopped) {
            let numSamples = numSamplesTemp - 1;
            while (numSamples > -1) {
                this.computeAudioChannels();
                this.sequencerClocks -= 1;
                if (this.sequencerClocks === 0) {
                    this.audioComputeSequencer();
                    this.sequencerClocks = GBEMU_0x2000;
                }
                numSamples -= 1;
            }
        }
    }
    audioJIT() {
        //debugLog('This is audioJIT');
        //Audio Sample Generation Timing:
        if (settings[GBEMU_0]) {
            this.generateAudio(this.audioTicks);
        }
        else {
            this.generateAudioFake(this.audioTicks);
        }
        this.audioTicks = GBEMU_0;
    }
    audioComputeSequencer() {
        //debugLog('This is audioComputeSequencer');
        switch (this.sequencePosition++) {
            case 0:
                this.clockAudioLength();
                break;
            case GBEMU_2:
                this.clockAudioLength();
                this.clockAudioSweep();
                break;
            case GBEMU_4:
                this.clockAudioLength();
                break;
            case GBEMU_6:
                this.clockAudioLength();
                this.clockAudioSweep();
                break;
            case GBEMU_7:
                this.clockAudioEnvelope();
                this.sequencePosition = 0;
            default:
                break;
        }
    }
    clockAudioLength() {
        //Channel 1:
        if (this.channel1totalLength > 1) {
            this.channel1totalLength -= 1;
        }
        else if (this.channel1totalLength === 1) {
            this.channel1totalLength = 0;
            this.channel1EnableCheck();
            this.memory[GBEMU_0xFF26] &= GBEMU_0xFE; //Channel #1 On Flag Off
        }
        //Channel GBEMU_2:
        if (this.channel2totalLength > 1) {
            this.channel2totalLength -= 1;
        }
        else if (this.channel2totalLength === 1) {
            this.channel2totalLength = 0;
            this.channel2EnableCheck();
            this.memory[GBEMU_0xFF26] &= GBEMU_0xFD; //Channel #GBEMU_2 On Flag Off
        }
        //Channel GBEMU_3:
        if (this.channel3totalLength > 1) {
            this.channel3totalLength -= 1;
        }
        else if (this.channel3totalLength === 1) {
            this.channel3totalLength = 0;
            this.channel3EnableCheck();
            this.memory[GBEMU_0xFF26] &= GBEMU_0xFB; //Channel #GBEMU_3 On Flag Off
        }
        //Channel GBEMU_4:
        if (this.channel4totalLength > 1) {
            this.channel4totalLength -= 1;
        }
        else if (this.channel4totalLength === 1) {
            this.channel4totalLength = 0;
            this.channel4EnableCheck();
            this.memory[GBEMU_0xFF26] &= GBEMU_0xF7; //Channel #GBEMU_4 On Flag Off
        }
    }
    clockAudioSweep() {
        //Channel 1:
        if (!this.channel1SweepFault && this.channel1timeSweep > 0) {
            this.channel1timeSweep -= 1;
            if (this.channel1timeSweep === 0) {
                this.runAudioSweep();
            }
        }
    }
    runAudioSweep() {
        //debugLog('This is runAudioSweep');
        //Channel 1:
        if (this.channel1lastTimeSweep > 0) {
            if (this.channel1frequencySweepDivider > 0) {
                if (this.channel1numSweep > 0) {
                    this.channel1numSweep -= 1;
                    if (this.channel1decreaseSweep) {
                        this.channel1ShadowFrequency -= this.channel1ShadowFrequency >> this.channel1frequencySweepDivider;
                        this.channel1frequency = this.channel1ShadowFrequency & GBEMU_0x7FF;
                        this.channel1FrequencyTracker = (GBEMU_0x800 - this.channel1frequency) << GBEMU_2;
                    }
                    else {
                        this.channel1ShadowFrequency += this.channel1ShadowFrequency >> this.channel1frequencySweepDivider;
                        this.channel1frequency = this.channel1ShadowFrequency;
                        if (this.channel1ShadowFrequency <= GBEMU_0x7FF) {
                            this.channel1FrequencyTracker = (GBEMU_0x800 - this.channel1frequency) << GBEMU_2;
                            //Run overflow check twice:
                            if (this.channel1ShadowFrequency + (this.channel1ShadowFrequency >> this.channel1frequencySweepDivider) > GBEMU_0x7ff) {
                                this.channel1SweepFault = true;
                                this.channel1EnableCheck();
                                this.memory[GBEMU_0xFF26] &= GBEMU_0xFE; //Channel #1 On Flag Off
                            }
                        }
                        else {
                            this.channel1frequency &= GBEMU_0x7FF;
                            this.channel1SweepFault = true;
                            this.channel1EnableCheck();
                            this.memory[GBEMU_0xFF26] &= GBEMU_0xFE; //Channel #1 On Flag Off
                        }
                    }
                }
                this.channel1timeSweep = this.channel1lastTimeSweep;
            }
            else {
                //Channel has sweep disabled and timer becomes a length counter:
                this.channel1SweepFault = true;
                this.channel1EnableCheck();
            }
        }
    }
    clockAudioEnvelope() {
        //debugLog('This is clockAudioEnvelope');
        //Channel 1:
        if (this.channel1envelopeSweepsLast > -1) {
            if (this.channel1envelopeSweeps > 0) {
                this.channel1envelopeSweeps -= 1;
            }
            else {
                if (!this.channel1envelopeType) {
                    if (this.channel1envelopeVolume > 0) {
                        this.channel1envelopeVolume -= 1;
                        this.channel1envelopeSweeps = this.channel1envelopeSweepsLast;
                        this.channel1OutputLevelCache();
                    }
                    else {
                        this.channel1envelopeSweepsLast = -1;
                    }
                }
                else if (this.channel1envelopeVolume < GBEMU_0xF) {
                    this.channel1envelopeVolume += 1;
                    this.channel1envelopeSweeps = this.channel1envelopeSweepsLast;
                    this.channel1OutputLevelCache();
                }
                else {
                    this.channel1envelopeSweepsLast = -1;
                }
            }
        }
        //Channel GBEMU_2:
        if (this.channel2envelopeSweepsLast > -1) {
            if (this.channel2envelopeSweeps > 0) {
                this.channel2envelopeSweeps -= 1;
            }
            else {
                if (!this.channel2envelopeType) {
                    if (this.channel2envelopeVolume > 0) {
                        this.channel2envelopeVolume -= 1;
                        this.channel2envelopeSweeps = this.channel2envelopeSweepsLast;
                        this.channel2OutputLevelCache();
                    }
                    else {
                        this.channel2envelopeSweepsLast = -1;
                    }
                }
                else if (this.channel2envelopeVolume < GBEMU_0xf) {
                    this.channel2envelopeVolume += 1;
                    this.channel2envelopeSweeps = this.channel2envelopeSweepsLast;
                    this.channel2OutputLevelCache();
                }
                else {
                    this.channel2envelopeSweepsLast = -1;
                }
            }
        }
        //Channel GBEMU_4:
        if (this.channel4envelopeSweepsLast > -1) {
            if (this.channel4envelopeSweeps > 0) {
                this.channel4envelopeSweeps -= 1;
            }
            else {
                if (!this.channel4envelopeType) {
                    if (this.channel4envelopeVolume > 0) {
                        this.channel4envelopeVolume -= 1;
                        this.channel4currentVolume = this.channel4envelopeVolume << this.channel4VolumeShifter;
                        this.channel4envelopeSweeps = this.channel4envelopeSweepsLast;
                        this.channel4UpdateCache();
                    }
                    else {
                        this.channel4envelopeSweepsLast = -1;
                    }
                }
                else if (this.channel4envelopeVolume < GBEMU_0xF) {
                    this.channel4envelopeVolume += 1;
                    this.channel4currentVolume = this.channel4envelopeVolume << this.channel4VolumeShifter;
                    this.channel4envelopeSweeps = this.channel4envelopeSweepsLast;
                    this.channel4UpdateCache();
                }
                else {
                    this.channel4envelopeSweepsLast = -1;
                }
            }
        }
    }
    computeAudioChannels() {
        //Channel 1 counter:
        this.channel1FrequencyCounter -= 1;
        if (this.channel1FrequencyCounter === 0) {
            this.channel1FrequencyCounter = this.channel1FrequencyTracker;
            this.channel1DutyTracker = (this.channel1DutyTracker + 1) & GBEMU_0x7;
            this.channel1OutputLevelTrimaryCache();
        }
        //Channel GBEMU_2 counter:
        this.channel2FrequencyCounter -= 1;
        if (this.channel2FrequencyCounter === 0) {
            this.channel2FrequencyCounter = this.channel2FrequencyTracker;
            this.channel2DutyTracker = (this.channel2DutyTracker + 1) & GBEMU_0x7;
            this.channel2OutputLevelTrimaryCache();
        }
        //Channel GBEMU_3 counter:
        this.channel3Counter -= 1;
        if (this.channel3Counter === 0) {
            if (this.channel3canPlay) {
                this.channel3lastSampleLookup = (this.channel3lastSampleLookup + 1) & GBEMU_0x1f;
            }
            this.channel3Counter = this.channel3FrequencyPeriod;
            this.channel3UpdateCache();
        }
        //Channel GBEMU_4 counter:
        this.channel4Counter -= 1;
        if (this.channel4Counter === 0) {
            this.channel4lastSampleLookup = (this.channel4lastSampleLookup + 1) & this.channel4BitRange;
            this.channel4Counter = this.channel4FrequencyPeriod;
            this.channel4UpdateCache();
        }
    }
    channel1EnableCheck() {
        this.channel1Enabled = (this.channel1consecutive || this.channel1totalLength > 0) && !this.channel1SweepFault && this.channel1canPlay;
        this.channel1OutputLevelSecondaryCache();
    }
    channel1VolumeEnableCheck() {
        this.channel1canPlay = this.memory[GBEMU_0xFF12] > GBEMU_7;
        this.channel1EnableCheck();
        this.channel1OutputLevelSecondaryCache();
    }
    channel1OutputLevelCache() {
        //debugLog('This is channel1OutputLevelCache');
        this.channel1currentSampleLeft = this.leftChannel1 ? this.channel1envelopeVolume : 0;
        this.channel1currentSampleRight = this.rightChannel1 ? this.channel1envelopeVolume : 0;
        this.channel1OutputLevelSecondaryCache();
    }
    channel1OutputLevelSecondaryCache() {
        //debugLog('This is channel1OutputLevelSecondaryCache');
        if (this.channel1Enabled) {
            //is true
            this.channel1currentSampleLeftSecondary = this.channel1currentSampleLeft;
            this.channel1currentSampleRightSecondary = this.channel1currentSampleRight;
        }
        else {
            //is false
            this.channel1currentSampleLeftSecondary = 0;
            this.channel1currentSampleRightSecondary = 0;
        }
        this.channel1OutputLevelTrimaryCache();
    }
    channel1OutputLevelTrimaryCache() {
        //debugLog('This is channel1OutputLevelTrimaryCache');
        if (this.channel1CachedDuty[this.channel1DutyTracker]) {
            //is true
            this.channel1currentSampleLeftTrimary = this.channel1currentSampleLeftSecondary;
            this.channel1currentSampleRightTrimary = this.channel1currentSampleRightSecondary;
        }
        else {
            // is false
            this.channel1currentSampleLeftTrimary = 0;
            this.channel1currentSampleRightTrimary = 0;
        }
        this.mixerOutputLevelCache();
    }
    channel2EnableCheck() {
        this.channel2Enabled = (this.channel2consecutive || this.channel2totalLength > 0) && this.channel2canPlay;
        this.channel2OutputLevelSecondaryCache();
    }
    channel2VolumeEnableCheck() {
        this.channel2canPlay = this.memory[GBEMU_0xFF17] > GBEMU_7;
        this.channel2EnableCheck();
        this.channel2OutputLevelSecondaryCache();
    }
    channel2OutputLevelCache() {
        //debugLog('This is channel2OutputLevelCache');
        this.channel2currentSampleLeft = this.leftChannel2 ? this.channel2envelopeVolume : 0;
        this.channel2currentSampleRight = this.rightChannel2 ? this.channel2envelopeVolume : 0;
        this.channel2OutputLevelSecondaryCache();
    }
    channel2OutputLevelSecondaryCache() {
        //debugLog('This is channel2OutputLevelSecondaryCache');
        if (this.channel2Enabled) {
            //is true
            this.channel2currentSampleLeftSecondary = this.channel2currentSampleLeft;
            this.channel2currentSampleRightSecondary = this.channel2currentSampleRight;
        }
        else {
            //is false
            this.channel2currentSampleLeftSecondary = 0;
            this.channel2currentSampleRightSecondary = 0;
        }
        this.channel2OutputLevelTrimaryCache();
    }
    channel2OutputLevelTrimaryCache() {
        //debugLog('This is channel2OutputLevelTrimaryCache');
        if (this.channel2CachedDuty[this.channel2DutyTracker]) {
            //is true
            this.channel2currentSampleLeftTrimary = this.channel2currentSampleLeftSecondary;
            this.channel2currentSampleRightTrimary = this.channel2currentSampleRightSecondary;
        }
        else {
            //is false
            this.channel2currentSampleLeftTrimary = 0;
            this.channel2currentSampleRightTrimary = 0;
        }
        this.mixerOutputLevelCache();
    }
    channel3EnableCheck() {
        this.channel3Enabled = /*this.channel3canPlay && */ this.channel3consecutive || this.channel3totalLength > 0;
        this.channel3OutputLevelSecondaryCache();
    }
    channel3OutputLevelCache() {
        this.channel3currentSampleLeft = this.leftChannel3 ? this.cachedChannel3Sample : 0;
        this.channel3currentSampleRight = this.rightChannel3 ? this.cachedChannel3Sample : 0;
        this.channel3OutputLevelSecondaryCache();
    }
    channel3OutputLevelSecondaryCache() {
        if (this.channel3Enabled) {
            //is true
            this.channel3currentSampleLeftSecondary = this.channel3currentSampleLeft;
            this.channel3currentSampleRightSecondary = this.channel3currentSampleRight;
        }
        else {
            //is false
            this.channel3currentSampleLeftSecondary = 0;
            this.channel3currentSampleRightSecondary = 0;
        }
        this.mixerOutputLevelCache();
    }
    channel4EnableCheck() {
        this.channel4Enabled = (this.channel4consecutive || this.channel4totalLength > 0) && this.channel4canPlay;
        this.channel4OutputLevelSecondaryCache();
    }
    channel4VolumeEnableCheck() {
        this.channel4canPlay = this.memory[GBEMU_0xFF21] > GBEMU_7;
        this.channel4EnableCheck();
        this.channel4OutputLevelSecondaryCache();
    }
    channel4OutputLevelCache() {
        this.channel4currentSampleLeft = this.leftChannel4 ? this.cachedChannel4Sample : 0;
        this.channel4currentSampleRight = this.rightChannel4 ? this.cachedChannel4Sample : 0;
        this.channel4OutputLevelSecondaryCache();
    }
    channel4OutputLevelSecondaryCache() {
        if (this.channel4Enabled) {
            //is true
            this.channel4currentSampleLeftSecondary = this.channel4currentSampleLeft;
            this.channel4currentSampleRightSecondary = this.channel4currentSampleRight;
        }
        else {
            //is false
            this.channel4currentSampleLeftSecondary = 0;
            this.channel4currentSampleRightSecondary = 0;
        }
        this.mixerOutputLevelCache();
    }
    mixerOutputLevelCache() {
        this.mixerOutputCache =
            (((this.channel1currentSampleLeftTrimary +
                this.channel2currentSampleLeftTrimary +
                this.channel3currentSampleLeftSecondary +
                this.channel4currentSampleLeftSecondary) *
                this.vinLeftChannelMasterVolume) <<
                GBEMU_9) +
                (this.channel1currentSampleRightTrimary +
                    this.channel2currentSampleRightTrimary +
                    this.channel3currentSampleRightSecondary +
                    this.channel4currentSampleRightSecondary) *
                    this.vinRightChannelMasterVolume;
    }
    channel3UpdateCache() {
        this.cachedChannel3Sample = this.channel3PCM[this.channel3lastSampleLookup] >> this.channel3patternType;
        this.channel3OutputLevelCache();
    }
    channel3WriteRAM(addressTemp, data) {
        let address = addressTemp;
        if (this.channel3canPlay) {
            this.audioJIT();
            //address = this.channel3lastSampleLookup >> 1;
        }
        this.memory[GBEMU_0xFF30 | address] = data;
        address <<= 1;
        this.channel3PCM[address] = data >> GBEMU_4;
        this.channel3PCM[address | 1] = data & GBEMU_0xF;
    }
    channel4UpdateCache() {
        this.cachedChannel4Sample = this.noiseSampleTable[this.channel4currentVolume | this.channel4lastSampleLookup];
        this.channel4OutputLevelCache();
    }
    run() {
        //debugLog('This is GameBoyCore run');
        //The preprocessing before the actual iteration loop:
        if ((this.stopEmulator & GBEMU_2) === 0) {
            if ((this.stopEmulator & GBEMU_1) === 1) {
                if (!this.cpuStopped) {
                    this.stopEmulator = GBEMU_0;
                    this.drewFrame = false;
                    this.audioUnderrunAdjustment();
                    //RTC clocking.
                    this.clockUpdate();
                    if (!this.halt) {
                        this.executeIteration();
                    }
                    else {
                        //Finish the HALT rundown execution.
                        this.cpuTicks = GBEMU_0;
                        this.calculateHALTPeriod();
                        if (this.halt) {
                            this.updateCoreFull(); //true
                        }
                        else {
                            this.executeIteration();
                        }
                    }
                    this.requestDraw(); //Request the graphics target to be updated
                }
                else {
                    this.audioUnderrunAdjustment();
                    this.audioTicks += this.cpuCyclesTotal;
                    this.audioJIT();
                    this.stopEmulator |= GBEMU_1; //End current loop.
                }
            }
            else {
                //We can only get here if there was an internal error, but the loop was restarted.
                cout('Iterator restarted a faulted core.', GBEMU_2);
                pausePlay();
            }
        }
    }
    executeIteration() {
        //debugLog('This is executeIteration');
        //Iterate the interpreter loop:
        let opcodeToExecute = 0;
        let timedTicks = 0;
        while (this.stopEmulator === 0) {
            //Interrupt Arming:
            switch (this.irqEnableDelay) {
                case GBEMU_1:
                    this.ime = true;
                    this.checkIRQMatching();
                case GBEMU_2:
                    this.irqEnableDelay -= 1;
                default:
                    break;
            }
            //Is an IRQ set to fire?:
            if (this.irqLineMatched > GBEMU_0) {
                //ime is true and and interrupt was matched:
                this.launchIRQ();
            }
            opcodeToExecute = this.memoryReader[this.programCounter](this, this.programCounter); //Fetch the current opcode
            //Increment the program counter to the next instruction:
            this.programCounter = (this.programCounter + 1) & GBEMU_0xFFFF;
            //Check for the program counter quirk:
            if (this.skipPCIncrement) {
                this.programCounter = (this.programCounter - 1) & GBEMU_0xFFFF;
                this.skipPCIncrement = false;
            }
            //Get how many CPU cycles the current instruction counts for:
            this.cpuTicks = this.tickTable[opcodeToExecute];
            //Execute the current instruction:
            this.opCode[opcodeToExecute](this);
            //Update the clocking for the LCD emulation:
            //Update the state (Inlined updateCoreFull manually here):
            this.lcdTicks += this.cpuTicks >> this.doubleSpeedShifter;
            //Scan Line and STAT Mode Control
            this.lcdControl[this.actualScanLine](this);
            //Single-speed relative timing for A/V emulation:
            timedTicks = this.cpuTicks >> this.doubleSpeedShifter;
            //Audio Timing
            this.audioTicks += timedTicks;
            //Emulator Timing
            this.emulatorTicks += timedTicks;
            //CPU Timers:
            this.divTicks += this.cpuTicks;
            if (this.timaEnabled) {
                //TIMA Timing
                this.timerTicks += this.cpuTicks;
                while (this.timerTicks >= this.tacClocker) {
                    this.timerTicks -= this.tacClocker;
                    this.memory[GBEMU_0xFF05] += GBEMU_1;
                    if (this.memory[GBEMU_0xFF05] === GBEMU_0x100) {
                        this.memory[GBEMU_0xFF05] = this.memory[GBEMU_0xFF06];
                        this.interruptsRequested |= GBEMU_0x4;
                        this.checkIRQMatching();
                    }
                }
            }
            if (this.serialTimer > GBEMU_0) {
                //Serial Timing
                //IRQ Counter:
                this.serialTimer -= this.cpuTicks;
                if (this.serialTimer <= GBEMU_0) {
                    this.interruptsRequested |= GBEMU_0x8;
                    this.checkIRQMatching();
                }
                //Bit Shit Counter:
                this.serialShiftTimer -= this.cpuTicks;
                if (this.serialShiftTimer <= GBEMU_0) {
                    this.serialShiftTimer = this.serialShiftTimerAllocated;
                    this.memory[GBEMU_0xFF01] = ((this.memory[GBEMU_0xFF01] << GBEMU_1) & GBEMU_0xFE) | GBEMU_0x01; //We could shift in actual link data here if we were to implement such!!!
                }
            }
            //End of iteration routine:
            if (this.emulatorTicks >= this.cpuCyclesTotal) {
                this.iterationEndRoutine();
            }
            // Start of code added for benchmarking:
            this.instructions += 1;
            if (this.instructions > this.totalInstructions) {
                this.iterationEndRoutine();
                this.stopEmulator |= GBEMU_2;
                checkFinalState();
            }
            // End of code added for benchmarking.
        }
    }
    iterationEndRoutine() {
        //debugLog('This is iterationEndRoutine');
        if ((this.stopEmulator & GBEMU_0x1) === 0) {
            this.audioJIT(); //Make sure we at least output once per iteration.
            //Update DIV Alignment (Integer overflow safety):
            this.memory[GBEMU_0xFF04] = (this.memory[GBEMU_0xFF04] + (this.divTicks >> GBEMU_8)) & GBEMU_0xFF;
            this.divTicks &= GBEMU_0xFF;
            //Update emulator flags:
            this.stopEmulator |= 1; //End current loop.
            this.emulatorTicks -= this.cpuCyclesTotal;
            this.cpuCyclesTotalCurrent += this.cpuCyclesTotalRoundoff;
            this.recalculateIterationClockLimit();
        }
    }
    handleSTOP() {
        //debugLog('This is handleSTOP');
        this.cpuStopped = true; //Stop CPU until joypad input changes.
        this.iterationEndRoutine();
        if (this.emulatorTicks < 0) {
            this.audioTicks -= this.emulatorTicks;
            this.audioJIT();
        }
    }
    recalculateIterationClockLimit() {
        //debugLog('This is recalculateIterationClockLimit');
        let endModulus = this.cpuCyclesTotalCurrent % GBEMU_4;
        this.cpuCyclesTotal = this.cpuCyclesTotalBase + this.cpuCyclesTotalCurrent - endModulus;
        this.cpuCyclesTotalCurrent = endModulus;
    }
    scanLineMode2() {
        //OAM Search Period
        if (this.statTracker !== 1) {
            if (this.mode2TriggerSTAT) {
                this.interruptsRequested |= GBEMU_0x2;
                this.checkIRQMatching();
            }
            this.statTracker = 1;
            this.modeSTAT = GBEMU_2;
        }
    }
    scanLineMode3() {
        //Scan Line Drawing Period
        if (this.modeSTAT !== GBEMU_3) {
            if (this.statTracker === 0 && this.mode2TriggerSTAT) {
                this.interruptsRequested |= GBEMU_0x2;
                this.checkIRQMatching();
            }
            this.statTracker = 1;
            this.modeSTAT = GBEMU_3;
        }
    }
    scanLineMode0() {
        //Horizontal Blanking Period
        if (this.modeSTAT !== 0) {
            if (this.statTracker !== GBEMU_2) {
                if (this.statTracker === 0) {
                    if (this.mode2TriggerSTAT) {
                        this.interruptsRequested |= GBEMU_0x2;
                        this.checkIRQMatching();
                    }
                    this.modeSTAT = GBEMU_3;
                }
                this.incrementScanLineQueue();
                this.updateSpriteCount(this.actualScanLine);
                this.statTracker = GBEMU_2;
            }
            if (this.lcdTicks >= this.spriteCount) {
                if (this.hdmaRunning) {
                    this.executeHDMA();
                }
                if (this.mode0TriggerSTAT) {
                    this.interruptsRequested |= GBEMU_0x2;
                    this.checkIRQMatching();
                }
                this.statTracker = GBEMU_3;
                this.modeSTAT = 0;
            }
        }
    }
    clocksUntilLYCMatch() {
        //debugLog('This is clocksUntilLYCMatch');
        if (this.memory[GBEMU_0xFF45] !== 0) {
            if (this.memory[GBEMU_0xFF45] > this.actualScanLine) {
                return GBEMU_456 * (this.memory[GBEMU_0xFF45] - this.actualScanLine);
            }
            return GBEMU_456 * (GBEMU_154 - this.actualScanLine + this.memory[GBEMU_0xFF45]);
        }
        return GBEMU_456 * (this.actualScanLine === GBEMU_153 && this.memory[GBEMU_0xFF44] === 0 ? GBEMU_154 : GBEMU_153 - this.actualScanLine) + GBEMU_8;
    }
    clocksUntilMode0() {
        //debugLog('This is clocksUntilMode0');
        switch (this.modeSTAT) {
            case 0:
                if (this.actualScanLine === GBEMU_143) {
                    this.updateSpriteCount(0);
                    return this.spriteCount + GBEMU_5016;
                }
                this.updateSpriteCount(this.actualScanLine + 1);
                return this.spriteCount + GBEMU_456;
            case GBEMU_2:
            case GBEMU_3:
                this.updateSpriteCount(this.actualScanLine);
                return this.spriteCount;
            case 1:
                this.updateSpriteCount(0);
                return this.spriteCount + GBEMU_456 * (GBEMU_154 - this.actualScanLine);
            default:
                return 0;
        }
    }
    updateSpriteCount(line) {
        this.spriteCount = GBEMU_252;
        if (this.cGBC && this.gfxSpriteShow) {
            //Is the window enabled and are we in CGB mode?
            let lineAdjusted = line + GBEMU_0x10;
            let yoffset = 0;
            let yCap = this.gfxSpriteNormalHeight ? GBEMU_0x8 : GBEMU_0x10;
            let oamAddress = GBEMU_0xFE00;
            while (oamAddress < GBEMU_0xFEA0 && this.spriteCount < GBEMU_312) {
                yoffset = lineAdjusted - this.memory[oamAddress];
                if (yoffset > -1 && yoffset < yCap) {
                    this.spriteCount += GBEMU_6;
                }
                oamAddress += GBEMU_4;
            }
        }
    }
    matchLYC() {
        //LYC Register Compare
        //debugLog('This is matchLYC');
        if (this.memory[GBEMU_0xFF44] === this.memory[GBEMU_0xFF45]) {
            this.memory[GBEMU_0xFF41] |= GBEMU_0x04;
            if (this.lycMatchTriggerSTAT) {
                this.interruptsRequested |= GBEMU_0x2;
                this.checkIRQMatching();
            }
        }
        else {
            this.memory[GBEMU_0xFF41] &= GBEMU_0x7B;
        }
    }
    updateCore() {
        //debugLog('This is updateCore');
        //Update the clocking for the LCD emulation:
        this.lcdTicks += this.cpuTicks >> this.doubleSpeedShifter; //LCD Timing
        this.lcdControl[this.actualScanLine](this); //Scan Line and STAT Mode Control
        //Single-speed relative timing for A/V emulation:
        let timedTicks = this.cpuTicks >> this.doubleSpeedShifter; //CPU clocking can be updated from the LCD handling.
        this.audioTicks += timedTicks; //Audio Timing
        this.emulatorTicks += timedTicks; //Emulator Timing
        //CPU Timers:
        this.divTicks += this.cpuTicks; //DIV Timing
        if (this.timaEnabled) {
            //TIMA Timing
            this.timerTicks += this.cpuTicks;
            while (this.timerTicks >= this.tacClocker) {
                this.timerTicks -= this.tacClocker;
                this.memory[GBEMU_0xFF05] += 1;
                if (this.memory[GBEMU_0xFF05] === GBEMU_0x100) {
                    this.memory[GBEMU_0xFF05] = this.memory[GBEMU_0xFF06];
                    this.interruptsRequested |= GBEMU_0x4;
                    this.checkIRQMatching();
                }
            }
        }
        if (this.serialTimer > 0) {
            //Serial Timing
            //IRQ Counter:
            this.serialTimer -= this.cpuTicks;
            if (this.serialTimer <= 0) {
                this.interruptsRequested |= GBEMU_0x8;
                this.checkIRQMatching();
            }
            //Bit Shit Counter:
            this.serialShiftTimer -= this.cpuTicks;
            if (this.serialShiftTimer <= 0) {
                this.serialShiftTimer = this.serialShiftTimerAllocated;
                this.memory[GBEMU_0xFF01] = ((this.memory[GBEMU_0xFF01] << 1) & GBEMU_0xFE) | GBEMU_0x01; //We could shift in actual link data here if we were to implement such!!!
            }
        }
    }
    updateCoreFull() {
        //debugLog('This is updateCoreFull');
        //Update the state machine:
        this.updateCore();
        //End of iteration routine:
        if (this.emulatorTicks >= this.cpuCyclesTotal) {
            this.iterationEndRoutine();
        }
    }
    initializeLCDController() {
        //debugLog('This is initializeLCDController');
        //Display on hanlding:
        let line = 0;
        while (line < GBEMU_154) {
            if (line < GBEMU_143) {
                //We're on a normal scan line:
                this.lineControl[line] = (parentObj) => {
                    if (parentObj.lcdTicks < GBEMU_80) {
                        parentObj.scanLineMode2();
                    }
                    else if (parentObj.lcdTicks < GBEMU_252) {
                        parentObj.scanLineMode3();
                    }
                    else if (parentObj.lcdTicks < GBEMU_456) {
                        parentObj.scanLineMode0();
                    }
                    else {
                        //We're on a new scan line:
                        parentObj.lcdTicks -= GBEMU_456;
                        if (parentObj.statTracker !== GBEMU_3) {
                            //Make sure the mode 0 handler was run at least once per scan line:
                            if (parentObj.statTracker !== GBEMU_2) {
                                if (parentObj.statTracker === 0 && parentObj.mode2TriggerSTAT) {
                                    parentObj.interruptsRequested |= GBEMU_0x2;
                                }
                                parentObj.incrementScanLineQueue();
                            }
                            if (parentObj.hdmaRunning) {
                                parentObj.executeHDMA();
                            }
                            if (parentObj.mode0TriggerSTAT) {
                                parentObj.interruptsRequested |= GBEMU_0x2;
                            }
                        }
                        //Update the scanline registers and assert the LYC counter:
                        parentObj.memory[GBEMU_0xFF44] += 1;
                        parentObj.actualScanLine = parentObj.memory[GBEMU_0xFF44];
                        //Perform a LYC counter assert:
                        if (parentObj.actualScanLine === parentObj.memory[GBEMU_0xFF45]) {
                            parentObj.memory[GBEMU_0xFF41] |= GBEMU_0x04;
                            if (parentObj.lycMatchTriggerSTAT) {
                                parentObj.interruptsRequested |= GBEMU_0x2;
                            }
                        }
                        else {
                            parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x7B;
                        }
                        parentObj.checkIRQMatching();
                        //Reset our mode contingency variables:
                        parentObj.statTracker = 0;
                        parentObj.modeSTAT = GBEMU_2;
                        parentObj.lineControl[parentObj.actualScanLine](parentObj); //Scan Line and STAT Mode Control.
                    }
                };
            }
            else if (line === GBEMU_143) {
                //We're on the last visible scan line of the LCD screen:
                this.lineControl[GBEMU_143] = (parentObj) => {
                    if (parentObj.lcdTicks < GBEMU_80) {
                        parentObj.scanLineMode2();
                    }
                    else if (parentObj.lcdTicks < GBEMU_252) {
                        parentObj.scanLineMode3();
                    }
                    else if (parentObj.lcdTicks < GBEMU_456) {
                        parentObj.scanLineMode0();
                    }
                    else {
                        //Starting V-Blank:
                        //Just finished the last visible scan line:
                        parentObj.lcdTicks -= GBEMU_456;
                        if (parentObj.statTracker !== GBEMU_3) {
                            //Make sure the mode 0 handler was run at least once per scan line:
                            if (parentObj.statTracker !== GBEMU_2) {
                                if (parentObj.statTracker === 0 && parentObj.mode2TriggerSTAT) {
                                    parentObj.interruptsRequested |= GBEMU_0x2;
                                }
                                parentObj.incrementScanLineQueue();
                            }
                            if (parentObj.hdmaRunning) {
                                parentObj.executeHDMA();
                            }
                            if (parentObj.mode0TriggerSTAT) {
                                parentObj.interruptsRequested |= GBEMU_0x2;
                            }
                        }
                        //Update the scanline registers and assert the LYC counter:
                        parentObj.actualScanLine = GBEMU_144;
                        parentObj.memory[GBEMU_0xFF44] = GBEMU_144;
                        //Perform a LYC counter assert:
                        if (parentObj.memory[GBEMU_0xFF45] === GBEMU_144) {
                            parentObj.memory[GBEMU_0xFF41] |= GBEMU_0x04;
                            if (parentObj.lycMatchTriggerSTAT) {
                                parentObj.interruptsRequested |= GBEMU_0x2;
                            }
                        }
                        else {
                            parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x7B;
                        }
                        //Reset our mode contingency variables:
                        parentObj.statTracker = 0;
                        //Update our state for v-blank:
                        parentObj.modeSTAT = 1;
                        parentObj.interruptsRequested |= parentObj.mode1TriggerSTAT ? GBEMU_0x3 : GBEMU_0x1;
                        parentObj.checkIRQMatching();
                        //Attempt to blit out to our canvas:
                        if (parentObj.drewBlank === 0) {
                            //Ensure JIT framing alignment:
                            if (parentObj.totalLinesPassed < GBEMU_144 || (parentObj.totalLinesPassed === GBEMU_144 && parentObj.midScanlineOffset > -1)) {
                                //Make sure our gfx are up-to-date:
                                parentObj.graphicsJITVBlank();
                                //Draw the frame:
                                parentObj.prepareFrame();
                            }
                        }
                        else {
                            //LCD off takes at least GBEMU_2 frames:
                            parentObj.drewBlank -= 1;
                        }
                        parentObj.lineControl[GBEMU_144](parentObj); //Scan Line and STAT Mode Control.
                    }
                };
            }
            else if (line < GBEMU_153) {
                //In VBlank
                this.lineControl[line] = (parentObj) => {
                    if (parentObj.lcdTicks >= GBEMU_456) {
                        //We're on a new scan line:
                        parentObj.lcdTicks -= GBEMU_456;
                        parentObj.memory[GBEMU_0xFF44] += 1;
                        parentObj.actualScanLine = parentObj.memory[GBEMU_0xFF44];
                        //Perform a LYC counter assert:
                        if (parentObj.actualScanLine === parentObj.memory[GBEMU_0xFF45]) {
                            parentObj.memory[GBEMU_0xFF41] |= GBEMU_0x04;
                            if (parentObj.lycMatchTriggerSTAT) {
                                parentObj.interruptsRequested |= GBEMU_0x2;
                                parentObj.checkIRQMatching();
                            }
                        }
                        else {
                            parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x7B;
                        }
                        parentObj.lineControl[parentObj.actualScanLine](parentObj); //Scan Line and STAT Mode Control.
                    }
                };
            }
            else {
                //VBlank Ending (We're on the last actual scan line)
                this.lineControl[GBEMU_153] = (parentObj) => {
                    if (parentObj.lcdTicks >= GBEMU_8) {
                        if (parentObj.statTracker !== GBEMU_4 && parentObj.memory[GBEMU_0xFF44] === GBEMU_153) {
                            parentObj.memory[GBEMU_0xFF44] = 0; //LY register resets to 0 early.
                            //Perform a LYC counter assert:
                            if (parentObj.memory[GBEMU_0xFF45] === 0) {
                                parentObj.memory[GBEMU_0xFF41] |= GBEMU_0x04;
                                if (parentObj.lycMatchTriggerSTAT) {
                                    parentObj.interruptsRequested |= GBEMU_0x2;
                                    parentObj.checkIRQMatching();
                                }
                            }
                            else {
                                parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x7B;
                            }
                            parentObj.statTracker = GBEMU_4;
                        }
                        if (parentObj.lcdTicks >= GBEMU_456) {
                            //We reset back to the beginning:
                            parentObj.lcdTicks -= GBEMU_456;
                            parentObj.statTracker = 0;
                            parentObj.actualScanLine = 0;
                            parentObj.lineControl[0](parentObj); //Scan Line and STAT Mode Control.
                        }
                    }
                };
            }
            line += 1;
        }
    }
    displayShowOff() {
        //debugLog('This is DisplayShowOff')
        if (this.drewBlank === 0) {
            //Output a blank screen to the output framebuffer:
            this.clearFrameBuffer();
            this.drewFrame = true;
        }
        this.drewBlank = GBEMU_2;
    }
    executeHDMA() {
        this.dMAWrite(1);
        if (this.halt) {
            if (this.lcdTicks - this.spriteCount < ((GBEMU_4 >> this.doubleSpeedShifter) | GBEMU_0x20)) {
                //HALT clocking correction:
                this.cpuTicks = GBEMU_4 + ((GBEMU_0x20 + this.spriteCount) << this.doubleSpeedShifter);
                this.lcdTicks = this.spriteCount + ((GBEMU_4 >> this.doubleSpeedShifter) | GBEMU_0x20);
            }
        }
        else {
            this.lcdTicks += (GBEMU_4 >> this.doubleSpeedShifter) | GBEMU_0x20; //LCD Timing Update For HDMA.
        }
        if (this.memory[GBEMU_0xFF55] === 0) {
            this.hdmaRunning = false;
            this.memory[GBEMU_0xFF55] = GBEMU_0xFF; //Transfer completed ('Hidden last step,' since some roms don't imply this, but most do).
        }
        else {
            this.memory[GBEMU_0xFF55] -= 1;
        }
    }
    clockUpdate() {
        //debugLog('This is clockUpdate');
        if (this.cTimeR) {
            let dateObj = new NewDate(); // The line is changed for benchmarking.
            let newTime = dateObj.getTime();
            let timeElapsed = newTime - this.lastIteration; //Get the numnber of milliseconds since this last executed.
            this.lastIteration = newTime;
            if (this.cTimeR && !this.rtcHalt) {
                //Update the MBC3 RTC:
                this.rtcSeconds += timeElapsed / GBEMU_1000;
                while (this.rtcSeconds >= GBEMU_60) {
                    //System can stutter, so the seconds difference can get large, thus the 'while'.
                    this.rtcSeconds -= GBEMU_60;
                    this.rtcMinutes += 1;
                    if (this.rtcMinutes >= GBEMU_60) {
                        this.rtcMinutes -= GBEMU_60;
                        this.rtcHours += 1;
                        if (this.rtcHours >= GBEMU_24) {
                            this.rtcHours -= GBEMU_24;
                            this.rtcDays += 1;
                            if (this.rtcDays >= GBEMU_512) {
                                this.rtcDays -= GBEMU_512;
                                this.rtcDayOverFlow = true;
                            }
                        }
                    }
                }
            }
        }
    }
    prepareFrame() {
        //debugLog('This is prepareFrame');
        //Copy the internal frame buffer to the output buffer:
        this.swizzleFrameBuffer();
        this.drewFrame = true;
    }
    requestDraw() {
        //debugLog('This is requestDraw');
        if (this.drewFrame) {
            this.dispatchDraw();
        }
    }
    dispatchDraw() {
        //debugLog('This is dispatchDraw');
        let canvasRGBALength = this.offscreenRGBCount;
        if (canvasRGBALength > 0) {
            //We actually updated the graphics internally, so copy out:
            let frameBuffer = canvasRGBALength === GBEMU_92160 ? this.swizzledFrame : this.resizeFrameBuffer();
            let canvasData = this.canvasBuffer.data;
            let bufferIndex = 0;
            let canvasIndex = 0;
            while (canvasIndex < canvasRGBALength) {
                canvasData[canvasIndex++] = frameBuffer[bufferIndex++];
                canvasData[canvasIndex++] = frameBuffer[bufferIndex++];
                canvasData[canvasIndex++] = frameBuffer[bufferIndex++];
                canvasIndex += 1;
            }
            this.graphicsBlit();
        }
    }
    swizzleFrameBuffer() {
        //debugLog('This is swizzleFrameBuffer');
        //Convert our dirty GBEMU_24-bit (GBEMU_24-bit, with internal render flags above it) framebuffer to an GBEMU_8-bit buffer with separate indices for the RGB channels:
        let frameBuffer = this.frameBuffer;
        let bufferIndex = 0;
        let canvasIndex = 0;
        while (canvasIndex < GBEMU_69120) {
            this.swizzledFrame[canvasIndex++] = (frameBuffer[bufferIndex] >> GBEMU_16) & GBEMU_0xFF; //Red
            this.swizzledFrame[canvasIndex++] = (frameBuffer[bufferIndex] >> GBEMU_8) & GBEMU_0xFF; //Green
            this.swizzledFrame[canvasIndex++] = frameBuffer[bufferIndex++] & GBEMU_0xFF; //Blue
        }
    }
    clearFrameBuffer() {
        //debugLog('This is clearFrameBuffer');
        let bufferIndex = 0;
        if (this.cGBC || this.colorizedGBPalettes) {
            while (bufferIndex < GBEMU_69120) {
                this.swizzledFrame[bufferIndex++] = GBEMU_248;
            }
        }
        else {
            while (bufferIndex < GBEMU_69120) {
                this.swizzledFrame[bufferIndex++] = GBEMU_239;
                this.swizzledFrame[bufferIndex++] = GBEMU_255;
                this.swizzledFrame[bufferIndex++] = GBEMU_222;
            }
        }
    }
    resizeFrameBuffer() {
        //debugLog('This is resizeFrameBuffer');
        //Return a reference to the generated resized framebuffer:
        return this.resizer.resize(this.swizzledFrame);
    }
    compileResizeFrameBufferFunction() {
        //debugLog('This is compileResizeFrameBufferFunction');
        if (this.offscreenRGBCount > 0) {
            this.resizer = new Resize(GBEMU_160, GBEMU_144, this.offscreenWidth, this.offscreenHeight, false, true);
        }
    }
    renderScanLine(scanlineToRender) {
        this.pixelStart = scanlineToRender * GBEMU_160;
        if (this.bgEnabled) {
            this.pixelEnd = 160;
            this.bgLayerRender(scanlineToRender);
            this.windowLayerRender(scanlineToRender);
        }
        else {
            let pixelLine = (scanlineToRender + 1) * GBEMU_160;
            let defaultColor = this.cGBC || this.colorizedGBPalettes ? GBEMU_0xF8F8F8 : GBEMU_0xEFFFDE;
            let pixelPosition = scanlineToRender * GBEMU_160 + this.currentX;
            while (pixelPosition < pixelLine) {
                this.frameBuffer[pixelPosition] = defaultColor;
                pixelPosition += 1;
            }
        }
        this.spriteLayerRender(scanlineToRender);
        this.currentX = 0;
        this.midScanlineOffset = -1;
    }
    renderMidScanLine() {
        if (this.actualScanLine < GBEMU_144 && this.modeSTAT === GBEMU_3) {
            //TODO: Get this accurate:
            if (this.midScanlineOffset === -1) {
                this.midScanlineOffset = this.backgroundX & GBEMU_0x7;
            }
            if (this.lcdTicks >= GBEMU_82) {
                this.pixelEnd = this.lcdTicks - GBEMU_74;
                this.pixelEnd = Math.min(this.pixelEnd - this.midScanlineOffset - (this.pixelEnd % GBEMU_0x8), GBEMU_160);
                if (this.bgEnabled) {
                    this.pixelStart = this.lastUnrenderedLine * GBEMU_160;
                    this.bgLayerRender(this.lastUnrenderedLine);
                    this.windowLayerRender(this.lastUnrenderedLine);
                    //TODO: Do midscanline JIT for sprites...
                }
                else {
                    let pixelLine = this.lastUnrenderedLine * GBEMU_160 + this.pixelEnd;
                    let defaultColor = this.cGBC || this.colorizedGBPalettes ? GBEMU_0xF8F8F8 : GBEMU_0xEFFFDE;
                    let pixelPosition = this.lastUnrenderedLine * GBEMU_160 + this.currentX;
                    while (pixelPosition < pixelLine) {
                        this.frameBuffer[pixelPosition] = defaultColor;
                        pixelPosition += 1;
                    }
                }
                this.currentX = this.pixelEnd;
            }
        }
    }
    initializeModeSpecificArrays() {
        //debugLog('This is initializeModeSpecificArrays');
        this.lcdControl = this.lcdIsOn ? this.lineControl : this.disPlayOffControl;
        if (this.cGBC) {
            this.gbcOBJRawPalette = this.getTypedArray(GBEMU_0x40, 0, 'uint8');
            this.gbcBGRawPalette = this.getTypedArray(GBEMU_0x40, 0, 'uint8');
            this.gbcOBJPalette = this.getTypedArray(GBEMU_0x20, GBEMU_0x1000000, 'int32');
            this.gbcBGPalette = this.getTypedArray(GBEMU_0x40, 0, 'int32');
            this.bgCHRBank2.array = this.getTypedArray(GBEMU_0x800, 0, 'uint8');
            this.bgCHRCurrentBank = this.currvramBank > 0 ? this.bgCHRBank2 : this.bgCHRBank1;
            this.tileCache = this.generateCacheArray(GBEMU_0xf80);
        }
        else {
            this.gbOBJPalette = this.getTypedArray(GBEMU_8, 0, 'int32');
            this.gbBGPalette = this.getTypedArray(GBEMU_4, 0, 'int32');
            this.bgPalette = this.gbBGPalette;
            this.objPalette = this.gbOBJPalette;
            this.tileCache = this.generateCacheArray(GBEMU_0x700);
            this.sortBuffer = this.getTypedArray(GBEMU_0x100, 0, 'uint8');
            this.oamAddressCache = this.getTypedArray(GBEMU_10, 0, 'int32');
        }
        this.renderPathBuild();
    }
    gBCtoGBModeAdjust() {
        //debugLog('This is GBCtoGBModeAdjust');
        cout('Stepping down from GBC mode.', 0);
        this.bgCHRBank2.array = new Int32Array();
        this.vram = new Int32Array();
        this.gbcMemory = new Int32Array();
        this.bgCHRCurrentBank.array = new Int32Array();
        this.tileCache.length = GBEMU_0x700;
        if (settings[GBEMU_4]) {
            this.gbBGColorizedPalette = this.getTypedArray(GBEMU_4, 0, 'int32');
            this.gbOBJColorizedPalette = this.getTypedArray(GBEMU_8, 0, 'int32');
            this.cachedBGPaletteConversion = this.getTypedArray(GBEMU_4, 0, 'int32');
            this.cachedOBJPaletteConversion = this.getTypedArray(GBEMU_8, 0, 'int32');
            this.bgPalette = this.gbBGColorizedPalette;
            this.objPalette = this.gbOBJColorizedPalette;
            this.gbOBJPalette = null;
            this.gbBGPalette = null;
            this.getGBCColor();
        }
        else {
            this.gbOBJPalette = this.getTypedArray(GBEMU_8, 0, 'int32');
            this.gbBGPalette = this.getTypedArray(GBEMU_4, 0, 'int32');
            this.bgPalette = this.gbBGPalette;
            this.objPalette = this.gbOBJPalette;
        }
        this.sortBuffer = this.getTypedArray(GBEMU_0x100, 0, 'uint8');
        this.oamAddressCache = this.getTypedArray(GBEMU_10, 0, 'int32');
        this.renderPathBuild();
        this.memoryReadJumpCompile();
        this.memoryWriteJumpCompile();
    }
    renderPathBuild() {
        //debugLog('This is renderPathBuild');
        if (!this.cGBC) {
            this.bgLayerRender = this.bGGBLayerRender;
            this.windowLayerRender = this.windowGBLayerRender;
            this.spriteLayerRender = this.spriteGBLayerRender;
        }
        else {
            this.priorityFlaggingPathRebuild();
            this.spriteLayerRender = this.spriteGBCLayerRender;
        }
    }
    priorityFlaggingPathRebuild() {
        //debugLog('This is priorityFlaggingPathRebuild');
        if (this.bgPriorityEnabled) {
            this.bgLayerRender = this.bGGBCLayerRender;
            this.windowLayerRender = this.windowGBCLayerRender;
        }
        else {
            this.bgLayerRender = this.bGGBCLayerRenderNoPriorityFlagging;
            this.windowLayerRender = this.windowGBCLayerRenderNoPriorityFlagging;
        }
    }
    rGBTint(value) {
        //Adjustment for the GBC's tinting (According to Gambatte):
        let r = value & GBEMU_0x1f;
        let g = (value >> GBEMU_5) & GBEMU_0x1f;
        let b = (value >> GBEMU_10) & GBEMU_0x1f;
        return (((r * GBEMU_13 + g * GBEMU_2 + b) >> 1) << GBEMU_16) | ((g * GBEMU_3 + b) << GBEMU_9) | ((r * GBEMU_3 + g * GBEMU_2 + b * GBEMU_11) >> 1);
    }
    getGBCColor() {
        //debugLog('This is getGBCColor');
        //GBC Colorization of DMG roms:
        //BG
        let counter = 0;
        while (counter < GBEMU_4) {
            let adjustedIndex = counter << 1;
            //BG
            this.cachedBGPaletteConversion[counter] = this.rGBTint((this.gbcBGRawPalette[adjustedIndex | 1] << GBEMU_8) | this.gbcBGRawPalette[adjustedIndex]);
            //OBJ 1
            this.cachedOBJPaletteConversion[counter] = this.rGBTint((this.gbcOBJRawPalette[adjustedIndex | 1] << GBEMU_8) | this.gbcOBJRawPalette[adjustedIndex]);
            counter += 1;
        }
        //OBJ GBEMU_2
        counter = GBEMU_4;
        while (counter < GBEMU_8) {
            let adjustedIndex = counter << 1;
            this.cachedOBJPaletteConversion[counter] = this.rGBTint((this.gbcOBJRawPalette[adjustedIndex | 1] << GBEMU_8) | this.gbcOBJRawPalette[adjustedIndex]);
            counter += 1;
        }
        //Update the palette entries:
        this.updateGBBGPalette = this.updateGBColorizedBGPalette;
        this.updateGBOBJPalette = this.updateGBColorizedOBJPalette;
        this.updateGBBGPalette(this.memory[GBEMU_0xFF47]);
        this.updateGBOBJPalette(0, this.memory[GBEMU_0xFF48]);
        this.updateGBOBJPalette(1, this.memory[GBEMU_0xFF49]);
        this.colorizedGBPalettes = true;
    }
    updateGBRegularBGPalette(data) {
        //debugLog('This is updateGBRegularBGPalette');
        this.gbBGPalette[0] = this.colors[data & GBEMU_0x03] | GBEMU_0x2000000;
        this.gbBGPalette[1] = this.colors[(data >> GBEMU_2) & GBEMU_0x03];
        this.gbBGPalette[GBEMU_2] = this.colors[(data >> GBEMU_4) & GBEMU_0x03];
        this.gbBGPalette[GBEMU_3] = this.colors[data >> GBEMU_6];
    }
    updateGBColorizedBGPalette(data) {
        //debugLog('This is updateGBColorizedBGPalette');
        //GB colorization:
        this.gbBGColorizedPalette[0] = this.cachedBGPaletteConversion[data & GBEMU_0x03] | GBEMU_0x2000000;
        this.gbBGColorizedPalette[1] = this.cachedBGPaletteConversion[(data >> GBEMU_2) & GBEMU_0x03];
        this.gbBGColorizedPalette[GBEMU_2] = this.cachedBGPaletteConversion[(data >> GBEMU_4) & GBEMU_0x03];
        this.gbBGColorizedPalette[GBEMU_3] = this.cachedBGPaletteConversion[data >> GBEMU_6];
    }
    updateGBRegularOBJPalette(index, data) {
        //debugLog('This is updateGBRegularOBJPalette');
        this.gbOBJPalette[index | 1] = this.colors[(data >> GBEMU_2) & GBEMU_0x03];
        this.gbOBJPalette[index | GBEMU_2] = this.colors[(data >> GBEMU_4) & GBEMU_0x03];
        this.gbOBJPalette[index | GBEMU_3] = this.colors[data >> GBEMU_6];
    }
    updateGBColorizedOBJPalette(index, data) {
        //debugLog('This is updateGBColorizedOBJPalette');
        //GB colorization:
        this.gbOBJColorizedPalette[index | 1] = this.cachedOBJPaletteConversion[index | ((data >> GBEMU_2) & GBEMU_0x03)];
        this.gbOBJColorizedPalette[index | GBEMU_2] = this.cachedOBJPaletteConversion[index | ((data >> GBEMU_4) & GBEMU_0x03)];
        this.gbOBJColorizedPalette[index | GBEMU_3] = this.cachedOBJPaletteConversion[index | (data >> GBEMU_6)];
    }
    updateGBCBGPalette(indexTemp, dataTemp) {
        let index = indexTemp;
        let data = dataTemp;
        if (this.gbcBGRawPalette[index] !== data) {
            this.midScanLineJIT();
            //Update the color palette for BG tiles since it changed:
            this.gbcBGRawPalette[index] = data;
            if ((index & GBEMU_0x06) === 0) {
                //Palette 0 (Special tile Priority stuff)
                data = GBEMU_0x2000000 | this.rGBTint((this.gbcBGRawPalette[index | 1] << GBEMU_8) | this.gbcBGRawPalette[index & GBEMU_0x3E]);
                index >>= 1;
                this.gbcBGPalette[index] = data;
                this.gbcBGPalette[GBEMU_0x20 | index] = GBEMU_0x1000000 | data;
            }
            else {
                //Regular Palettes (No special crap)
                data = this.rGBTint((this.gbcBGRawPalette[index | 1] << GBEMU_8) | this.gbcBGRawPalette[index & GBEMU_0x3E]);
                index >>= 1;
                this.gbcBGPalette[index] = data;
                this.gbcBGPalette[GBEMU_0x20 | index] = GBEMU_0x1000000 | data;
            }
        }
    }
    updateGBCOBJPalette(index, data) {
        if (this.gbcOBJRawPalette[index] !== data) {
            //Update the color palette for OBJ tiles since it changed:
            this.gbcOBJRawPalette[index] = data;
            if ((index & GBEMU_0x06) > 0) {
                //Regular Palettes (No special crap)
                this.midScanLineJIT();
                this.gbcOBJPalette[index >> 1] =
                    GBEMU_0x1000000 | this.rGBTint((this.gbcOBJRawPalette[index | 1] << GBEMU_8) | this.gbcOBJRawPalette[index & GBEMU_0x3E]);
            }
        }
    }
    bGGBLayerRender(scanlineToRender) {
        //debugLog('This is BGGBLayerRender');
        let scrollYAdjusted = (this.backgroundY + scanlineToRender) & GBEMU_0xFF; //The line of the BG we're at.
        let tileYLine = (scrollYAdjusted & GBEMU_7) << GBEMU_3;
        let tileYDown = this.gfxBackgroundCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2); //The row of cached tiles  we're fetching from.
        let scrollXAdjusted = (this.backgroundX + this.currentX) & GBEMU_0xFF; //The scroll amount of the BG.
        let pixelPosition = this.pixelStart + this.currentX; //Current pixel we're working on.
        let pixelPositionEnd = this.pixelStart +
            (this.gfxWindowDisplay && scanlineToRender - this.windowY >= 0 ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd); //Make sure we do at most 160 pixels a scanline.
        let tileNumber = tileYDown + (scrollXAdjusted >> GBEMU_3);
        let chrCode = this.bgCHRBank1.array[tileNumber];
        if (chrCode < this.gfxBackgroundBankOffset) {
            chrCode |= GBEMU_0x100;
        }
        let tile = this.tileCache[chrCode].array;
        let texel = scrollXAdjusted & GBEMU_0x7;
        while (texel < GBEMU_8 && pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
            this.frameBuffer[pixelPosition++] = this.bgPalette[tile[tileYLine | texel++]];
            scrollXAdjusted += 1;
        }
        let scrollXAdjustedAligned = Math.min(pixelPositionEnd - pixelPosition, GBEMU_0x100 - scrollXAdjusted) >> GBEMU_3;
        scrollXAdjusted += scrollXAdjustedAligned << GBEMU_3;
        scrollXAdjustedAligned += tileNumber;
        while (tileNumber < scrollXAdjustedAligned) {
            tileNumber += 1;
            chrCode = this.bgCHRBank1.array[tileNumber];
            if (chrCode < this.gfxBackgroundBankOffset) {
                chrCode |= GBEMU_0x100;
            }
            tile = this.tileCache[chrCode].array;
            let texel = tileYLine;
            this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel]];
        }
        if (pixelPosition < pixelPositionEnd) {
            if (scrollXAdjusted < GBEMU_0x100) {
                tileNumber += 1;
                chrCode = this.bgCHRBank1.array[tileNumber];
                if (chrCode < this.gfxBackgroundBankOffset) {
                    chrCode |= GBEMU_0x100;
                }
                tile = this.tileCache[chrCode].array;
                let texel = tileYLine - 1;
                while (pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
                    texel += 1;
                    this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel]];
                    scrollXAdjusted += 1;
                }
            }
            scrollXAdjustedAligned = ((pixelPositionEnd - pixelPosition) >> GBEMU_3) + tileYDown;
            while (tileYDown < scrollXAdjustedAligned) {
                chrCode = this.bgCHRBank1.array[tileYDown++];
                if (chrCode < this.gfxBackgroundBankOffset) {
                    chrCode |= GBEMU_0x100;
                }
                tile = this.tileCache[chrCode].array;
                let texel = tileYLine;
                this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel]];
            }
            if (pixelPosition < pixelPositionEnd) {
                chrCode = this.bgCHRBank1.array[tileYDown];
                if (chrCode < this.gfxBackgroundBankOffset) {
                    chrCode |= GBEMU_0x100;
                }
                tile = this.tileCache[chrCode].array;
                switch (pixelPositionEnd - pixelPosition) {
                    case GBEMU_7:
                        this.frameBuffer[pixelPosition + GBEMU_6] = this.bgPalette[tile[tileYLine | GBEMU_6]];
                    case GBEMU_6:
                        this.frameBuffer[pixelPosition + GBEMU_5] = this.bgPalette[tile[tileYLine | GBEMU_5]];
                    case GBEMU_5:
                        this.frameBuffer[pixelPosition + GBEMU_4] = this.bgPalette[tile[tileYLine | GBEMU_4]];
                    case GBEMU_4:
                        this.frameBuffer[pixelPosition + GBEMU_3] = this.bgPalette[tile[tileYLine | GBEMU_3]];
                    case GBEMU_3:
                        this.frameBuffer[pixelPosition + GBEMU_2] = this.bgPalette[tile[tileYLine | GBEMU_2]];
                    case GBEMU_2:
                        this.frameBuffer[pixelPosition + 1] = this.bgPalette[tile[tileYLine | 1]];
                    case 1:
                        this.frameBuffer[pixelPosition] = this.bgPalette[tile[tileYLine]];
                    default:
                        break;
                }
            }
        }
    }
    bGGBCLayerRender(scanlineToRender) {
        let scrollYAdjusted = (this.backgroundY + scanlineToRender) & GBEMU_0xFF; //The line of the BG we're at.
        let tileYLine = (scrollYAdjusted & GBEMU_7) << GBEMU_3;
        let tileYDown = this.gfxBackgroundCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2); //The row of cached tiles   we're fetching from.
        let scrollXAdjusted = (this.backgroundX + this.currentX) & GBEMU_0xFF; //The scroll amount of the BG.
        let pixelPosition = this.pixelStart + this.currentX; //Current pixel we're working on.
        let pixelPositionEnd = this.pixelStart +
            (this.gfxWindowDisplay && scanlineToRender - this.windowY >= 0 ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd); //Make sure we do at most 160 pixels a scanline.
        let tileNumber = tileYDown + (scrollXAdjusted >> GBEMU_3);
        let chrCode = this.bgCHRBank1.array[tileNumber];
        if (chrCode < this.gfxBackgroundBankOffset) {
            chrCode |= GBEMU_0x100;
        }
        let attrCode = this.bgCHRBank2.array[tileNumber];
        let tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
        let palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
        let texel = scrollXAdjusted & GBEMU_0x7;
        while (texel < GBEMU_8 && pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[tileYLine | texel++]];
            scrollXAdjusted += 1;
        }
        let scrollXAdjustedAligned = Math.min(pixelPositionEnd - pixelPosition, GBEMU_0x100 - scrollXAdjusted) >> GBEMU_3;
        scrollXAdjusted += scrollXAdjustedAligned << GBEMU_3;
        scrollXAdjustedAligned += tileNumber;
        while (tileNumber < scrollXAdjustedAligned) {
            tileNumber += 1;
            chrCode = this.bgCHRBank1.array[tileNumber];
            if (chrCode < this.gfxBackgroundBankOffset) {
                chrCode |= GBEMU_0x100;
            }
            attrCode = this.bgCHRBank2.array[tileNumber];
            tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
            palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
            let texel = tileYLine;
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
        }
        if (pixelPosition < pixelPositionEnd) {
            if (scrollXAdjusted < GBEMU_0x100) {
                tileNumber += 1;
                chrCode = this.bgCHRBank1.array[tileNumber];
                if (chrCode < this.gfxBackgroundBankOffset) {
                    chrCode |= GBEMU_0x100;
                }
                attrCode = this.bgCHRBank2.array[tileNumber];
                tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
                texel = tileYLine - 1;
                while (pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
                    texel += 1;
                    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
                    scrollXAdjusted += 1;
                }
            }
            scrollXAdjustedAligned = ((pixelPositionEnd - pixelPosition) >> GBEMU_3) + tileYDown;
            while (tileYDown < scrollXAdjustedAligned) {
                chrCode = this.bgCHRBank1.array[tileYDown];
                if (chrCode < this.gfxBackgroundBankOffset) {
                    chrCode |= GBEMU_0x100;
                }
                attrCode = this.bgCHRBank2.array[tileYDown++];
                tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
                let texel = tileYLine;
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
            }
            if (pixelPosition < pixelPositionEnd) {
                chrCode = this.bgCHRBank1.array[tileYDown];
                if (chrCode < this.gfxBackgroundBankOffset) {
                    chrCode |= GBEMU_0x100;
                }
                attrCode = this.bgCHRBank2.array[tileYDown];
                tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
                switch (pixelPositionEnd - pixelPosition) {
                    case GBEMU_7:
                        this.frameBuffer[pixelPosition + GBEMU_6] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_6]];
                    case GBEMU_6:
                        this.frameBuffer[pixelPosition + GBEMU_5] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_5]];
                    case GBEMU_5:
                        this.frameBuffer[pixelPosition + GBEMU_4] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_4]];
                    case GBEMU_4:
                        this.frameBuffer[pixelPosition + GBEMU_3] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_3]];
                    case GBEMU_3:
                        this.frameBuffer[pixelPosition + GBEMU_2] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_2]];
                    case GBEMU_2:
                        this.frameBuffer[pixelPosition + 1] = this.gbcBGPalette[palette | tile[tileYLine | 1]];
                    case 1:
                        this.frameBuffer[pixelPosition] = this.gbcBGPalette[palette | tile[tileYLine]];
                    default:
                        break;
                }
            }
        }
    }
    bGGBCLayerRenderNoPriorityFlagging(scanlineToRender) {
        //debugLog('This is BGGBCLayerRenderNoPriorityFlagging');
        let scrollYAdjusted = (this.backgroundY + scanlineToRender) & GBEMU_0xFF; //The line of the BG we're at.
        let tileYLine = (scrollYAdjusted & GBEMU_7) << GBEMU_3;
        let tileYDown = this.gfxBackgroundCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2); //The row of cached tiles   // we're fetching from.
        let scrollXAdjusted = (this.backgroundX + this.currentX) & GBEMU_0xFF; //The scroll amount of the BG.
        let pixelPosition = this.pixelStart + this.currentX; //Current pixel we're working on.
        let pixelPositionEnd = this.pixelStart +
            (this.gfxWindowDisplay && scanlineToRender - this.windowY >= 0 ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd); //Make sure we do at most 160 pixels a scanline.
        let tileNumber = tileYDown + (scrollXAdjusted >> GBEMU_3);
        let chrCode = this.bgCHRBank1.array[tileNumber];
        if (chrCode < this.gfxBackgroundBankOffset) {
            chrCode |= GBEMU_0x100;
        }
        let attrCode = this.bgCHRBank2.array[tileNumber];
        let tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
        let palette = (attrCode & GBEMU_0x7) << GBEMU_2;
        let texel = scrollXAdjusted & GBEMU_0x7;
        while (texel < GBEMU_8 && pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[tileYLine | texel++]];
            scrollXAdjusted += 1;
        }
        let scrollXAdjustedAligned = Math.min(pixelPositionEnd - pixelPosition, GBEMU_0x100 - scrollXAdjusted) >> GBEMU_3;
        scrollXAdjusted += scrollXAdjustedAligned << GBEMU_3;
        scrollXAdjustedAligned += tileNumber;
        while (tileNumber < scrollXAdjustedAligned) {
            tileNumber += 1;
            chrCode = this.bgCHRBank1.array[tileNumber];
            if (chrCode < this.gfxBackgroundBankOffset) {
                chrCode |= GBEMU_0x100;
            }
            attrCode = this.bgCHRBank2.array[tileNumber];
            tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
            palette = (attrCode & GBEMU_0x7) << GBEMU_2;
            let texel = tileYLine;
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
            this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
        }
        if (pixelPosition < pixelPositionEnd) {
            if (scrollXAdjusted < GBEMU_0x100) {
                tileNumber += 1;
                chrCode = this.bgCHRBank1.array[tileNumber];
                if (chrCode < this.gfxBackgroundBankOffset) {
                    chrCode |= GBEMU_0x100;
                }
                attrCode = this.bgCHRBank2.array[tileNumber];
                tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                palette = (attrCode & GBEMU_0x7) << GBEMU_2;
                let texel = tileYLine - 1;
                while (pixelPosition < pixelPositionEnd && scrollXAdjusted < GBEMU_0x100) {
                    texel += 1;
                    this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
                    scrollXAdjusted += 1;
                }
            }
            scrollXAdjustedAligned = ((pixelPositionEnd - pixelPosition) >> GBEMU_3) + tileYDown;
            while (tileYDown < scrollXAdjustedAligned) {
                chrCode = this.bgCHRBank1.array[tileYDown];
                if (chrCode < this.gfxBackgroundBankOffset) {
                    chrCode |= GBEMU_0x100;
                }
                attrCode = this.bgCHRBank2.array[tileYDown++];
                tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                palette = (attrCode & GBEMU_0x7) << GBEMU_2;
                let texel = tileYLine;
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
            }
            if (pixelPosition < pixelPositionEnd) {
                chrCode = this.bgCHRBank1.array[tileYDown];
                if (chrCode < this.gfxBackgroundBankOffset) {
                    chrCode |= GBEMU_0x100;
                }
                attrCode = this.bgCHRBank2.array[tileYDown];
                tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                palette = (attrCode & GBEMU_0x7) << GBEMU_2;
                switch (pixelPositionEnd - pixelPosition) {
                    case GBEMU_7:
                        this.frameBuffer[pixelPosition + GBEMU_6] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_6]];
                    case GBEMU_6:
                        this.frameBuffer[pixelPosition + GBEMU_5] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_5]];
                    case GBEMU_5:
                        this.frameBuffer[pixelPosition + GBEMU_4] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_4]];
                    case GBEMU_4:
                        this.frameBuffer[pixelPosition + GBEMU_3] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_3]];
                    case GBEMU_3:
                        this.frameBuffer[pixelPosition + GBEMU_2] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_2]];
                    case GBEMU_2:
                        this.frameBuffer[pixelPosition + 1] = this.gbcBGPalette[palette | tile[tileYLine | 1]];
                    case 1:
                        this.frameBuffer[pixelPosition] = this.gbcBGPalette[palette | tile[tileYLine]];
                    default:
                        break;
                }
            }
        }
    }
    windowGBLayerRender(scanlineToRender) {
        //debugLog('This is WindowGBLayerRender');
        if (this.gfxWindowDisplay) {
            //Is the window enabled?
            let scrollYAdjusted = scanlineToRender - this.windowY; //The line of the BG we're at.
            if (scrollYAdjusted >= 0) {
                let scrollXRangeAdjusted = this.windowX > 0 ? this.windowX + this.currentX : this.currentX;
                let pixelPosition = this.pixelStart + scrollXRangeAdjusted;
                let pixelPositionEnd = this.pixelStart + this.pixelEnd;
                if (pixelPosition < pixelPositionEnd) {
                    let tileYLine = (scrollYAdjusted & GBEMU_0x7) << GBEMU_3;
                    let tileNumber = (this.gfxWindowCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2)) + (this.currentX >> GBEMU_3);
                    let chrCode = this.bgCHRBank1.array[tileNumber];
                    if (chrCode < this.gfxBackgroundBankOffset) {
                        chrCode |= GBEMU_0x100;
                    }
                    let tile = this.tileCache[chrCode].array;
                    let texel = (scrollXRangeAdjusted - this.windowX) & GBEMU_0x7;
                    scrollXRangeAdjusted = Math.min(GBEMU_8, texel + pixelPositionEnd - pixelPosition);
                    while (texel < scrollXRangeAdjusted) {
                        this.frameBuffer[pixelPosition++] = this.bgPalette[tile[tileYLine | texel++]];
                    }
                    scrollXRangeAdjusted = tileNumber + ((pixelPositionEnd - pixelPosition) >> GBEMU_3);
                    while (tileNumber < scrollXRangeAdjusted) {
                        tileNumber += 1;
                        chrCode = this.bgCHRBank1.array[tileNumber];
                        chrCode < this.gfxBackgroundBankOffset ? (chrCode |= GBEMU_0x100) : null;
                        tile = this.tileCache[chrCode].array;
                        texel = tileYLine;
                        this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.bgPalette[tile[texel]];
                    }
                    if (pixelPosition < pixelPositionEnd) {
                        tileNumber += 1;
                        chrCode = this.bgCHRBank1.array[tileNumber];
                        if (chrCode < this.gfxBackgroundBankOffset) {
                            chrCode |= GBEMU_0x100;
                        }
                        tile = this.tileCache[chrCode].array;
                        switch (pixelPositionEnd - pixelPosition) {
                            case GBEMU_7:
                                this.frameBuffer[pixelPosition + GBEMU_6] = this.bgPalette[tile[tileYLine | GBEMU_6]];
                            case GBEMU_6:
                                this.frameBuffer[pixelPosition + GBEMU_5] = this.bgPalette[tile[tileYLine | GBEMU_5]];
                            case GBEMU_5:
                                this.frameBuffer[pixelPosition + GBEMU_4] = this.bgPalette[tile[tileYLine | GBEMU_4]];
                            case GBEMU_4:
                                this.frameBuffer[pixelPosition + GBEMU_3] = this.bgPalette[tile[tileYLine | GBEMU_3]];
                            case GBEMU_3:
                                this.frameBuffer[pixelPosition + GBEMU_2] = this.bgPalette[tile[tileYLine | GBEMU_2]];
                            case GBEMU_2:
                                this.frameBuffer[pixelPosition + 1] = this.bgPalette[tile[tileYLine | 1]];
                            case 1:
                                this.frameBuffer[pixelPosition] = this.bgPalette[tile[tileYLine]];
                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
    windowGBCLayerRender(scanlineToRender) {
        if (this.gfxWindowDisplay) {
            //Is the window enabled?
            let scrollYAdjusted = scanlineToRender - this.windowY; //The line of the BG we're at.
            if (scrollYAdjusted >= 0) {
                let scrollXRangeAdjusted = this.windowX > 0 ? this.windowX + this.currentX : this.currentX;
                let pixelPosition = this.pixelStart + scrollXRangeAdjusted;
                let pixelPositionEnd = this.pixelStart + this.pixelEnd;
                if (pixelPosition < pixelPositionEnd) {
                    let tileYLine = (scrollYAdjusted & GBEMU_0x7) << GBEMU_3;
                    let tileNumber = (this.gfxWindowCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2)) + (this.currentX >> GBEMU_3);
                    let chrCode = this.bgCHRBank1.array[tileNumber];
                    if (chrCode < this.gfxBackgroundBankOffset) {
                        chrCode |= GBEMU_0x100;
                    }
                    let attrCode = this.bgCHRBank2.array[tileNumber];
                    let tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                    let palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
                    let texel = (scrollXRangeAdjusted - this.windowX) & GBEMU_0x7;
                    scrollXRangeAdjusted = Math.min(GBEMU_8, texel + pixelPositionEnd - pixelPosition);
                    while (texel < scrollXRangeAdjusted) {
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[tileYLine | texel++]];
                    }
                    scrollXRangeAdjusted = tileNumber + ((pixelPositionEnd - pixelPosition) >> GBEMU_3);
                    while (tileNumber < scrollXRangeAdjusted) {
                        tileNumber += 1;
                        chrCode = this.bgCHRBank1.array[tileNumber];
                        chrCode < this.gfxBackgroundBankOffset ? (chrCode |= GBEMU_0x100) : null;
                        attrCode = this.bgCHRBank2.array[tileNumber];
                        tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                        palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
                        texel = tileYLine;
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
                    }
                    if (pixelPosition < pixelPositionEnd) {
                        tileNumber += 1;
                        chrCode = this.bgCHRBank1.array[tileNumber];
                        if (chrCode < this.gfxBackgroundBankOffset) {
                            chrCode |= GBEMU_0x100;
                        }
                        attrCode = this.bgCHRBank2.array[tileNumber];
                        tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                        palette = ((attrCode & GBEMU_0x7) << GBEMU_2) | ((attrCode & GBEMU_0x80) >> GBEMU_2);
                        switch (pixelPositionEnd - pixelPosition) {
                            case GBEMU_7:
                                this.frameBuffer[pixelPosition + GBEMU_6] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_6]];
                            case GBEMU_6:
                                this.frameBuffer[pixelPosition + GBEMU_5] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_5]];
                            case GBEMU_5:
                                this.frameBuffer[pixelPosition + GBEMU_4] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_4]];
                            case GBEMU_4:
                                this.frameBuffer[pixelPosition + GBEMU_3] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_3]];
                            case GBEMU_3:
                                this.frameBuffer[pixelPosition + GBEMU_2] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_2]];
                            case GBEMU_2:
                                this.frameBuffer[pixelPosition + 1] = this.gbcBGPalette[palette | tile[tileYLine | 1]];
                            case 1:
                                this.frameBuffer[pixelPosition] = this.gbcBGPalette[palette | tile[tileYLine]];
                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
    windowGBCLayerRenderNoPriorityFlagging(scanlineToRender) {
        //debugLog('This is WindowGBCLayerRenderNoPriorityFlagging');
        if (this.gfxWindowDisplay) {
            let scrollYAdjusted = scanlineToRender - this.windowY; //The line of the BG we're at.
            if (scrollYAdjusted >= 0) {
                let scrollXRangeAdjusted = this.windowX > 0 ? this.windowX + this.currentX : this.currentX;
                let pixelPosition = this.pixelStart + scrollXRangeAdjusted;
                let pixelPositionEnd = this.pixelStart + this.pixelEnd;
                if (pixelPosition < pixelPositionEnd) {
                    let tileYLine = (scrollYAdjusted & GBEMU_0x7) << GBEMU_3;
                    let tileNumber = (this.gfxWindowCHRBankPosition | ((scrollYAdjusted & GBEMU_0xF8) << GBEMU_2)) + (this.currentX >> GBEMU_3);
                    let chrCode = this.bgCHRBank1.array[tileNumber];
                    if (chrCode < this.gfxBackgroundBankOffset) {
                        chrCode |= GBEMU_0x100;
                    }
                    let attrCode = this.bgCHRBank2.array[tileNumber];
                    let tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                    let palette = (attrCode & GBEMU_0x7) << GBEMU_2;
                    let texel = (scrollXRangeAdjusted - this.windowX) & GBEMU_0x7;
                    scrollXRangeAdjusted = Math.min(GBEMU_8, texel + pixelPositionEnd - pixelPosition);
                    while (texel < scrollXRangeAdjusted) {
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[tileYLine | texel++]];
                    }
                    scrollXRangeAdjusted = tileNumber + ((pixelPositionEnd - pixelPosition) >> GBEMU_3);
                    while (tileNumber < scrollXRangeAdjusted) {
                        tileNumber += 1;
                        chrCode = this.bgCHRBank1.array[tileNumber];
                        chrCode < this.gfxBackgroundBankOffset ? (chrCode |= GBEMU_0x100) : null;
                        attrCode = this.bgCHRBank2.array[tileNumber];
                        tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                        palette = (attrCode & GBEMU_0x7) << GBEMU_2;
                        texel = tileYLine;
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel++]];
                        this.frameBuffer[pixelPosition++] = this.gbcBGPalette[palette | tile[texel]];
                    }
                    if (pixelPosition < pixelPositionEnd) {
                        tileNumber += 1;
                        chrCode = this.bgCHRBank1.array[tileNumber];
                        if (chrCode < this.gfxBackgroundBankOffset) {
                            chrCode |= GBEMU_0x100;
                        }
                        attrCode = this.bgCHRBank2.array[tileNumber];
                        tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | chrCode].array;
                        palette = (attrCode & GBEMU_0x7) << GBEMU_2;
                        switch (pixelPositionEnd - pixelPosition) {
                            case GBEMU_7:
                                this.frameBuffer[pixelPosition + GBEMU_6] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_6]];
                            case GBEMU_6:
                                this.frameBuffer[pixelPosition + GBEMU_5] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_5]];
                            case GBEMU_5:
                                this.frameBuffer[pixelPosition + GBEMU_4] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_4]];
                            case GBEMU_4:
                                this.frameBuffer[pixelPosition + GBEMU_3] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_3]];
                            case GBEMU_3:
                                this.frameBuffer[pixelPosition + GBEMU_2] = this.gbcBGPalette[palette | tile[tileYLine | GBEMU_2]];
                            case GBEMU_2:
                                this.frameBuffer[pixelPosition + 1] = this.gbcBGPalette[palette | tile[tileYLine | 1]];
                            case 1:
                                this.frameBuffer[pixelPosition] = this.gbcBGPalette[palette | tile[tileYLine]];
                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
    spriteGBLayerRender(scanlineToRender) {
        //debugLog('This is SpriteGBLayerRender');
        if (this.gfxSpriteShow) {
            //Are sprites enabled?
            let lineAdjusted = scanlineToRender + GBEMU_0x10;
            let oamAddress = GBEMU_0xFE00;
            let yoffset = 0;
            let xcoord = 1;
            let xCoordStart = 0;
            let xCoordEnd = 0;
            let attrCode = 0;
            let palette = 0;
            let tile = new Int32Array();
            let data = 0;
            let spriteCount = 0;
            let length = 0;
            let currentPixel = 0;
            let linePixel = 0;
            //Clear our x-coord sort buffer:
            while (xcoord < GBEMU_168) {
                this.sortBuffer[xcoord++] = GBEMU_0xFF;
            }
            if (this.gfxSpriteNormalHeight) {
                //Draw the visible sprites:
                let length = this.findLowestSpriteDrawable(lineAdjusted, GBEMU_0x7);
                while (spriteCount < length) {
                    oamAddress = this.oamAddressCache[spriteCount];
                    yoffset = (lineAdjusted - this.memory[oamAddress]) << GBEMU_3;
                    attrCode = this.memory[oamAddress | GBEMU_3];
                    palette = (attrCode & GBEMU_0x10) >> GBEMU_2;
                    tile = this.tileCache[((attrCode & GBEMU_0x60) << GBEMU_4) | this.memory[oamAddress | GBEMU_0x2]].array;
                    linePixel = this.memory[oamAddress | 1];
                    xCoordStart = this.memory[oamAddress | 1];
                    xCoordEnd = Math.min(GBEMU_168 - linePixel, GBEMU_8);
                    xcoord = linePixel > GBEMU_7 ? 0 : GBEMU_8 - linePixel;
                    currentPixel = this.pixelStart + (linePixel > GBEMU_8 ? linePixel - GBEMU_8 : 0);
                    while (xcoord < xCoordEnd) {
                        if (this.sortBuffer[linePixel] > xCoordStart) {
                            if (this.frameBuffer[currentPixel] >= GBEMU_0x2000000) {
                                data = tile[yoffset | xcoord];
                                if (data > 0) {
                                    this.frameBuffer[currentPixel] = this.objPalette[palette | data];
                                    this.sortBuffer[linePixel] = xCoordStart;
                                }
                            }
                            else if (this.frameBuffer[currentPixel] < GBEMU_0x1000000) {
                                data = tile[yoffset | xcoord];
                                if (data > 0 && attrCode < GBEMU_0x80) {
                                    this.frameBuffer[currentPixel] = this.objPalette[palette | data];
                                    this.sortBuffer[linePixel] = xCoordStart;
                                }
                            }
                        }
                        xcoord += 1;
                        currentPixel += 1;
                        linePixel += 1;
                    }
                    spriteCount += 1;
                }
            }
            else {
                //Draw the visible sprites:
                let length = this.findLowestSpriteDrawable(lineAdjusted, GBEMU_0xF);
                while (spriteCount < length) {
                    oamAddress = this.oamAddressCache[spriteCount];
                    yoffset = (lineAdjusted - this.memory[oamAddress]) << GBEMU_3;
                    attrCode = this.memory[oamAddress | GBEMU_3];
                    palette = (attrCode & GBEMU_0x10) >> GBEMU_2;
                    if ((attrCode & GBEMU_0x40) === (GBEMU_0x40 & yoffset)) {
                        tile = this.tileCache[((attrCode & GBEMU_0x60) << GBEMU_4) | (this.memory[oamAddress | GBEMU_0x2] & GBEMU_0xFE)].array;
                    }
                    else {
                        tile = this.tileCache[((attrCode & GBEMU_0x60) << GBEMU_4) | this.memory[oamAddress | GBEMU_0x2] | 1].array;
                    }
                    yoffset &= GBEMU_0x3F;
                    xCoordStart = this.memory[oamAddress | 1];
                    linePixel = xCoordStart;
                    xCoordEnd = Math.min(GBEMU_168 - linePixel, GBEMU_8);
                    xcoord = linePixel > GBEMU_7 ? 0 : GBEMU_8 - linePixel;
                    currentPixel = this.pixelStart + (linePixel > GBEMU_8 ? linePixel - GBEMU_8 : 0);
                    while (xcoord < xCoordEnd) {
                        if (this.sortBuffer[linePixel] > xCoordStart) {
                            if (this.frameBuffer[currentPixel] >= GBEMU_0x2000000) {
                                data = tile[yoffset | xcoord];
                                if (data > 0) {
                                    this.frameBuffer[currentPixel] = this.objPalette[palette | data];
                                    this.sortBuffer[linePixel] = xCoordStart;
                                }
                            }
                            else if (this.frameBuffer[currentPixel] < GBEMU_0x1000000) {
                                data = tile[yoffset | xcoord];
                                if (data > 0 && attrCode < GBEMU_0x80) {
                                    this.frameBuffer[currentPixel] = this.objPalette[palette | data];
                                    this.sortBuffer[linePixel] = xCoordStart;
                                }
                            }
                        }
                        xcoord += 1;
                        currentPixel += 1;
                        linePixel += 1;
                    }
                    spriteCount += 1;
                }
            }
        }
    }
    findLowestSpriteDrawable(scanlineToRender, drawableRange) {
        //debugLog('This is findLowestSpriteDrawable');
        let address = GBEMU_0xFE00;
        let spriteCount = 0;
        let diff = 0;
        while (address < GBEMU_0xFEA0 && spriteCount < GBEMU_10) {
            diff = scanlineToRender - this.memory[address];
            if ((diff & drawableRange) === diff) {
                this.oamAddressCache[spriteCount++] = address;
            }
            address += GBEMU_4;
        }
        return spriteCount;
    }
    spriteGBCLayerRender(scanlineToRender) {
        if (this.gfxSpriteShow) {
            //Are sprites enabled?
            let oamAddress = GBEMU_0xFE00;
            let lineAdjusted = scanlineToRender + GBEMU_0x10;
            let yoffset = 0;
            let xcoord = 0;
            let endX = 0;
            let xCounter = 0;
            let attrCode = 0;
            let palette = 0;
            let tile = null;
            let data = 0;
            let currentPixel = 0;
            let spriteCount = 0;
            if (this.gfxSpriteNormalHeight) {
                while (oamAddress < GBEMU_0xFEA0 && spriteCount < GBEMU_10) {
                    yoffset = lineAdjusted - this.memory[oamAddress];
                    if ((yoffset & GBEMU_0x7) === yoffset) {
                        xcoord = this.memory[oamAddress | 1] - GBEMU_8;
                        endX = Math.min(GBEMU_160, xcoord + GBEMU_8);
                        attrCode = this.memory[oamAddress | GBEMU_3];
                        palette = (attrCode & GBEMU_7) << GBEMU_2;
                        tile = this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | this.memory[oamAddress | GBEMU_2]].array;
                        xCounter = xcoord > 0 ? xcoord : 0;
                        xcoord -= yoffset << GBEMU_3;
                        currentPixel = this.pixelStart + xCounter;
                        while (xCounter < endX) {
                            if (this.frameBuffer[currentPixel] >= GBEMU_0x2000000) {
                                data = tile[xCounter - xcoord];
                                if (data > 0) {
                                    this.frameBuffer[currentPixel] = this.gbcOBJPalette[palette | data];
                                }
                            }
                            else if (this.frameBuffer[currentPixel] < GBEMU_0x1000000) {
                                data = tile[xCounter - xcoord];
                                if (data > 0 && attrCode < GBEMU_0x80) {
                                    //Don't optimize for attrCode, as LICM-capable JITs should optimize its checks.
                                    this.frameBuffer[currentPixel] = this.gbcOBJPalette[palette | data];
                                }
                            }
                            xCounter += 1;
                            currentPixel += 1;
                        }
                        spriteCount += 1;
                    }
                    oamAddress += GBEMU_4;
                }
            }
            else {
                while (oamAddress < GBEMU_0xFEA0 && spriteCount < GBEMU_10) {
                    yoffset = lineAdjusted - this.memory[oamAddress];
                    if ((yoffset & GBEMU_0xF) === yoffset) {
                        xcoord = this.memory[oamAddress | 1] - GBEMU_8;
                        endX = Math.min(GBEMU_160, xcoord + GBEMU_8);
                        attrCode = this.memory[oamAddress | GBEMU_3];
                        palette = (attrCode & GBEMU_7) << GBEMU_2;
                        if ((attrCode & GBEMU_0x40) === (GBEMU_0x40 & (yoffset << GBEMU_3))) {
                            tile =
                                this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | (this.memory[oamAddress | GBEMU_0x2] & GBEMU_0xfe)].array;
                        }
                        else {
                            tile =
                                this.tileCache[((attrCode & GBEMU_0x08) << GBEMU_8) | ((attrCode & GBEMU_0x60) << GBEMU_4) | this.memory[oamAddress | GBEMU_0x2] | 1].array;
                        }
                        xCounter = xcoord > 0 ? xcoord : 0;
                        xcoord -= (yoffset & GBEMU_0x7) << GBEMU_3;
                        currentPixel = this.pixelStart + xCounter;
                        while (xCounter < endX) {
                            if (this.frameBuffer[currentPixel] >= GBEMU_0x2000000) {
                                data = tile[xCounter - xcoord];
                                if (data > 0) {
                                    this.frameBuffer[currentPixel] = this.gbcOBJPalette[palette | data];
                                }
                            }
                            else if (this.frameBuffer[currentPixel] < GBEMU_0x1000000) {
                                data = tile[xCounter - xcoord];
                                if (data > 0 && attrCode < GBEMU_0x80) {
                                    //Don't optimize for attrCode, as LICM-capable JITs should optimize its checks.
                                    this.frameBuffer[currentPixel] = this.gbcOBJPalette[palette | data];
                                }
                            }
                            xCounter += 1;
                            currentPixel += 1;
                        }
                        spriteCount += 1;
                    }
                    oamAddress += GBEMU_4;
                }
            }
        }
    }
    //Generate only a single tile line for the GB tile cache mode:
    generateGBTileLine(addressTemp) {
        //debugLog('This is generateGBTileLine');
        let address = addressTemp;
        let lineCopy = (this.memory[GBEMU_0x1 | address] << GBEMU_8) | this.memory[GBEMU_0x9FFE & address];
        let tileBlock = this.tileCache[(address & GBEMU_0x1FF0) >> GBEMU_4];
        address = (address & GBEMU_0xE) << GBEMU_2;
        tileBlock.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
        tileBlock.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
        tileBlock.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
        tileBlock.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
        tileBlock.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
        tileBlock.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
        tileBlock.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
        tileBlock.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
    }
    //Generate only a single tile line for the GBC tile cache mode (Bank 1):
    generateGBCTileLineBank1(addressTemp) {
        let address = addressTemp;
        let lineCopy = (this.memory[GBEMU_0x1 | address] << GBEMU_8) | this.memory[GBEMU_0x9FFE & address];
        address &= GBEMU_0x1FFE;
        let tileBlock1 = this.tileCache[address >> GBEMU_4];
        let tileBlock2 = this.tileCache[GBEMU_0x200 | (address >> GBEMU_4)];
        let tileBlock3 = this.tileCache[GBEMU_0x400 | (address >> GBEMU_4)];
        let tileBlock4 = this.tileCache[GBEMU_0x600 | (address >> GBEMU_4)];
        address = (address & GBEMU_0xE) << GBEMU_2;
        let addressFlipped = GBEMU_0x38 - address;
        tileBlock1.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
        tileBlock4.array[addressFlipped] = tileBlock1.array[address | GBEMU_7];
        tileBlock2.array[address] = tileBlock1.array[address | GBEMU_7];
        tileBlock3.array[addressFlipped | GBEMU_7] = tileBlock1.array[address | GBEMU_7];
        tileBlock1.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
        tileBlock4.array[addressFlipped | 1] = tileBlock1.array[address | GBEMU_6];
        tileBlock2.array[address | 1] = tileBlock1.array[address | GBEMU_6];
        tileBlock3.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | GBEMU_6];
        tileBlock1.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
        tileBlock4.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
        tileBlock2.array[address | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
        tileBlock3.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_5];
        tileBlock1.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
        tileBlock4.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
        tileBlock2.array[address | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
        tileBlock3.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_4];
        tileBlock1.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
        tileBlock4.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
        tileBlock2.array[address | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
        tileBlock3.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_3];
        tileBlock1.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
        tileBlock4.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
        tileBlock2.array[address | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
        tileBlock3.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_2];
        tileBlock1.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
        tileBlock4.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | 1];
        tileBlock2.array[address | GBEMU_6] = tileBlock1.array[address | 1];
        tileBlock3.array[addressFlipped | 1] = tileBlock1.array[address | 1];
        tileBlock1.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
        tileBlock4.array[addressFlipped | GBEMU_7] = tileBlock1.array[address];
        tileBlock2.array[address | GBEMU_7] = tileBlock1.array[address];
        tileBlock3.array[addressFlipped] = tileBlock1.array[address];
    }
    //Generate all the flip combinations for a full GBC vram bank 1 tile:
    generateGBCTileBank1(vramAddressTemp) {
        let vramAddress = vramAddressTemp;
        let address = vramAddress >> GBEMU_4;
        let tileBlock1 = this.tileCache[address];
        let tileBlock2 = this.tileCache[GBEMU_0x200 | address];
        let tileBlock3 = this.tileCache[GBEMU_0x400 | address];
        let tileBlock4 = this.tileCache[GBEMU_0x600 | address];
        let lineCopy = 0;
        vramAddress |= GBEMU_0x8000;
        address = 0;
        let addressFlipped = 56;
        do {
            lineCopy = (this.memory[GBEMU_0x1 | vramAddress] << GBEMU_8) | this.memory[vramAddress];
            tileBlock1.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
            tileBlock4.array[addressFlipped] = tileBlock1.array[address | GBEMU_7];
            tileBlock2.array[address] = tileBlock1.array[address | GBEMU_7];
            tileBlock3.array[addressFlipped | GBEMU_7] = tileBlock1.array[address | GBEMU_7];
            tileBlock1.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
            tileBlock4.array[addressFlipped | 1] = tileBlock1.array[address | GBEMU_6];
            tileBlock2.array[address | 1] = tileBlock1.array[address | GBEMU_6];
            tileBlock3.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | GBEMU_6];
            tileBlock1.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
            tileBlock4.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
            tileBlock2.array[address | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
            tileBlock3.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_5];
            tileBlock1.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
            tileBlock4.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
            tileBlock2.array[address | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
            tileBlock3.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_4];
            tileBlock1.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
            tileBlock4.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
            tileBlock2.array[address | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
            tileBlock3.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_3];
            tileBlock1.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
            tileBlock4.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
            tileBlock2.array[address | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
            tileBlock3.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_2];
            tileBlock1.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
            tileBlock4.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | 1];
            tileBlock2.array[address | GBEMU_6] = tileBlock1.array[address | 1];
            tileBlock3.array[addressFlipped | 1] = tileBlock1.array[address | 1];
            tileBlock1.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
            tileBlock4.array[addressFlipped | GBEMU_7] = tileBlock1.array[address];
            tileBlock2.array[address | GBEMU_7] = tileBlock1.array[address];
            tileBlock3.array[addressFlipped] = tileBlock1.array[address];
            address += GBEMU_8;
            addressFlipped -= GBEMU_8;
            vramAddress += GBEMU_2;
        } while (addressFlipped > -1);
    }
    //Generate only a single tile line for the GBC tile cache mode (Bank GBEMU_2):
    generateGBCTileLineBank2(addressTemp) {
        //debugLog('This is generateGBCTileLineBank2');
        let address = addressTemp;
        let lineCopy = (this.vram[GBEMU_0x1 | address] << GBEMU_8) | this.vram[GBEMU_0x1FFE & address];
        let tileBlock1 = this.tileCache[GBEMU_0x800 | (address >> GBEMU_4)];
        let tileBlock2 = this.tileCache[GBEMU_0xA00 | (address >> GBEMU_4)];
        let tileBlock3 = this.tileCache[GBEMU_0xC00 | (address >> GBEMU_4)];
        let tileBlock4 = this.tileCache[GBEMU_0xE00 | (address >> GBEMU_4)];
        address = (address & GBEMU_0xE) << GBEMU_2;
        let addressFlipped = GBEMU_0x38 - address;
        tileBlock1.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
        tileBlock4.array[addressFlipped] = tileBlock1.array[address | GBEMU_7];
        tileBlock2.array[address] = tileBlock1.array[address | GBEMU_7];
        tileBlock3.array[addressFlipped | GBEMU_7] = tileBlock1.array[address | GBEMU_7];
        tileBlock1.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
        tileBlock4.array[addressFlipped | 1] = tileBlock1.array[address | GBEMU_6];
        tileBlock2.array[address | 1] = tileBlock1.array[address | GBEMU_6];
        tileBlock3.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | GBEMU_6];
        tileBlock1.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
        tileBlock4.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
        tileBlock2.array[address | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
        tileBlock3.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_5];
        tileBlock1.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
        tileBlock4.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
        tileBlock2.array[address | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
        tileBlock3.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_4];
        tileBlock1.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
        tileBlock4.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
        tileBlock2.array[address | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
        tileBlock3.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_3];
        tileBlock1.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
        tileBlock4.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
        tileBlock2.array[address | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
        tileBlock3.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_2];
        tileBlock1.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
        tileBlock4.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | 1];
        tileBlock2.array[address | GBEMU_6] = tileBlock1.array[address | 1];
        tileBlock3.array[addressFlipped | 1] = tileBlock1.array[address | 1];
        tileBlock1.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
        tileBlock4.array[addressFlipped | GBEMU_7] = tileBlock1.array[address];
        tileBlock2.array[address | GBEMU_7] = tileBlock1.array[address];
        tileBlock3.array[addressFlipped] = tileBlock1.array[address];
    }
    //Generate all the flip combinations for a full GBC vram bank GBEMU_2 tile:
    generateGBCTileBank2(vramAddressTemp) {
        let vramAddress = vramAddressTemp;
        let address = vramAddress >> GBEMU_4;
        let tileBlock1 = this.tileCache[GBEMU_0x800 | address];
        let tileBlock2 = this.tileCache[GBEMU_0xA00 | address];
        let tileBlock3 = this.tileCache[GBEMU_0xC00 | address];
        let tileBlock4 = this.tileCache[GBEMU_0xE00 | address];
        let lineCopy = 0;
        address = 0;
        let addressFlipped = 56;
        do {
            lineCopy = (this.vram[GBEMU_0x1 | vramAddress] << GBEMU_8) | this.vram[vramAddress];
            tileBlock1.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
            tileBlock4.array[addressFlipped] = tileBlock1.array[address | GBEMU_7];
            tileBlock2.array[address] = tileBlock1.array[address | GBEMU_7];
            tileBlock3.array[addressFlipped | GBEMU_7] = tileBlock1.array[address | GBEMU_7];
            tileBlock1.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
            tileBlock4.array[addressFlipped | 1] = tileBlock1.array[address | GBEMU_6];
            tileBlock2.array[address | 1] = tileBlock1.array[address | GBEMU_6];
            tileBlock3.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | GBEMU_6];
            tileBlock1.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
            tileBlock4.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
            tileBlock2.array[address | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
            tileBlock3.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_5];
            tileBlock1.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
            tileBlock4.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
            tileBlock2.array[address | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
            tileBlock3.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_4];
            tileBlock1.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
            tileBlock4.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
            tileBlock2.array[address | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
            tileBlock3.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_3];
            tileBlock1.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
            tileBlock4.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
            tileBlock2.array[address | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
            tileBlock3.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_2];
            tileBlock1.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
            tileBlock4.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | 1];
            tileBlock2.array[address | GBEMU_6] = tileBlock1.array[address | 1];
            tileBlock3.array[addressFlipped | 1] = tileBlock1.array[address | 1];
            tileBlock1.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
            tileBlock4.array[addressFlipped | GBEMU_7] = tileBlock1.array[address];
            tileBlock2.array[address | GBEMU_7] = tileBlock1.array[address];
            tileBlock3.array[addressFlipped] = tileBlock1.array[address];
            address += GBEMU_8;
            addressFlipped -= GBEMU_8;
            vramAddress += GBEMU_2;
        } while (addressFlipped > -1);
    }
    //Generate only a single tile line for the GB tile cache mode (OAM accessible range):
    generateGBOAMTileLine(addressTemp) {
        //debugLog('This is generateGBOAMTileLine');
        let address = addressTemp;
        let lineCopy = (this.memory[GBEMU_0x1 | address] << GBEMU_8) | this.memory[GBEMU_0x9FFE & address];
        address &= GBEMU_0x1FFE;
        let tileBlock1 = this.tileCache[address >> GBEMU_4];
        let tileBlock2 = this.tileCache[GBEMU_0x200 | (address >> GBEMU_4)];
        let tileBlock3 = this.tileCache[GBEMU_0x400 | (address >> GBEMU_4)];
        let tileBlock4 = this.tileCache[GBEMU_0x600 | (address >> GBEMU_4)];
        address = (address & GBEMU_0xE) << GBEMU_2;
        let addressFlipped = GBEMU_0x38 - address;
        tileBlock1.array[address | GBEMU_7] = ((lineCopy & GBEMU_0x100) >> GBEMU_7) | (lineCopy & GBEMU_0x1);
        tileBlock4.array[addressFlipped] = tileBlock1.array[address | GBEMU_7];
        tileBlock2.array[address] = tileBlock1.array[address | GBEMU_7];
        tileBlock3.array[addressFlipped | GBEMU_7] = tileBlock1.array[address | GBEMU_7];
        tileBlock1.array[address | GBEMU_6] = ((lineCopy & GBEMU_0x200) >> GBEMU_8) | ((lineCopy & GBEMU_0x2) >> 1);
        tileBlock4.array[addressFlipped | 1] = tileBlock1.array[address | GBEMU_6];
        tileBlock2.array[address | 1] = tileBlock1.array[address | GBEMU_6];
        tileBlock3.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | GBEMU_6];
        tileBlock1.array[address | GBEMU_5] = ((lineCopy & GBEMU_0x400) >> GBEMU_9) | ((lineCopy & GBEMU_0x4) >> GBEMU_2);
        tileBlock4.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
        tileBlock2.array[address | GBEMU_2] = tileBlock1.array[address | GBEMU_5];
        tileBlock3.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_5];
        tileBlock1.array[address | GBEMU_4] = ((lineCopy & GBEMU_0x800) >> GBEMU_10) | ((lineCopy & GBEMU_0x8) >> GBEMU_3);
        tileBlock4.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
        tileBlock2.array[address | GBEMU_3] = tileBlock1.array[address | GBEMU_4];
        tileBlock3.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_4];
        tileBlock1.array[address | GBEMU_3] = ((lineCopy & GBEMU_0x1000) >> GBEMU_11) | ((lineCopy & GBEMU_0x10) >> GBEMU_4);
        tileBlock4.array[addressFlipped | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
        tileBlock2.array[address | GBEMU_4] = tileBlock1.array[address | GBEMU_3];
        tileBlock3.array[addressFlipped | GBEMU_3] = tileBlock1.array[address | GBEMU_3];
        tileBlock1.array[address | GBEMU_2] = ((lineCopy & GBEMU_0x2000) >> GBEMU_12) | ((lineCopy & GBEMU_0x20) >> GBEMU_5);
        tileBlock4.array[addressFlipped | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
        tileBlock2.array[address | GBEMU_5] = tileBlock1.array[address | GBEMU_2];
        tileBlock3.array[addressFlipped | GBEMU_2] = tileBlock1.array[address | GBEMU_2];
        tileBlock1.array[address | 1] = ((lineCopy & GBEMU_0x4000) >> GBEMU_13) | ((lineCopy & GBEMU_0x40) >> GBEMU_6);
        tileBlock4.array[addressFlipped | GBEMU_6] = tileBlock1.array[address | 1];
        tileBlock2.array[address | GBEMU_6] = tileBlock1.array[address | 1];
        tileBlock3.array[addressFlipped | 1] = tileBlock1.array[address | 1];
        tileBlock1.array[address] = ((lineCopy & GBEMU_0x8000) >> GBEMU_14) | ((lineCopy & GBEMU_0x80) >> GBEMU_7);
        tileBlock4.array[addressFlipped | GBEMU_7] = tileBlock1.array[address];
        tileBlock2.array[address | GBEMU_7] = tileBlock1.array[address];
        tileBlock3.array[addressFlipped] = tileBlock1.array[address];
    }
    graphicsJIT() {
        if (this.lcdIsOn) {
            this.totalLinesPassed = 0; //Mark frame for ensuring a JIT pass for the next framebuffer output.
            this.graphicsJITScanlineGroup();
        }
    }
    graphicsJITVBlank() {
        //debugLog('This is graphicsJITVBlank');
        //JIT the graphics to v-blank framing:
        this.totalLinesPassed += this.queuedScanLines;
        this.graphicsJITScanlineGroup();
    }
    graphicsJITScanlineGroup() {
        //Normal rendering JIT, where we try to do groups of scanlines at once:
        while (this.queuedScanLines > 0) {
            this.renderScanLine(this.lastUnrenderedLine);
            if (this.lastUnrenderedLine < GBEMU_143) {
                this.lastUnrenderedLine += 1;
            }
            else {
                this.lastUnrenderedLine = 0;
            }
            this.queuedScanLines -= 1;
        }
    }
    incrementScanLineQueue() {
        if (this.queuedScanLines < GBEMU_144) {
            this.queuedScanLines += 1;
        }
        else {
            this.currentX = 0;
            this.midScanlineOffset = -1;
            if (this.lastUnrenderedLine < GBEMU_143) {
                this.lastUnrenderedLine += 1;
            }
            else {
                this.lastUnrenderedLine = 0;
            }
        }
    }
    midScanLineJIT() {
        this.graphicsJIT();
        this.renderMidScanLine();
    }
    //Check for the highest priority IRQ to fire:
    launchIRQ() {
        //debugLog('This is launchIRQ');
        let bitShift = 0;
        let testbit = 1;
        do {
            //Check to see if an interrupt is enabled AND requested.
            if ((testbit & this.irqLineMatched) === testbit) {
                this.ime = false; //Reset the interrupt enabling.
                this.interruptsRequested -= testbit; //Reset the interrupt request.
                this.irqLineMatched = GBEMU_0; //Reset the IRQ assertion.
                //Interrupts have a certain clock cycle length:
                this.cpuTicks = GBEMU_20;
                //Set the stack pointer to the current program counter value:
                this.stackPointer = (this.stackPointer - 1) & GBEMU_0xFFFF;
                this.memoryWriter[this.stackPointer](this, this.stackPointer, this.programCounter >> GBEMU_8);
                this.stackPointer = (this.stackPointer - 1) & GBEMU_0xFFFF;
                this.memoryWriter[this.stackPointer](this, this.stackPointer, this.programCounter & GBEMU_0xFF);
                //Set the program counter to the interrupt's address:
                this.programCounter = GBEMU_0x40 | (bitShift << GBEMU_3);
                //Clock the core for mid-instruction updates:
                this.updateCore();
                return; //We only want the highest priority interrupt.
            }
            bitShift += 1;
            testbit = 1 << bitShift;
        } while (bitShift < GBEMU_5);
    }
    /*
    Check for IRQs to be fired while not in HALT:
  */
    checkIRQMatching() {
        if (this.ime) {
            this.irqLineMatched = this.interruptsEnabled & this.interruptsRequested & GBEMU_0x1f;
        }
    }
    calculateHALTPeriod() {
        //debugLog('This is calculateHALTPeriod');
        //Initialize our variables and start our prediction:
        let currentClocks = 0;
        if (!this.halt) {
            this.halt = true;
            currentClocks = -1;
            let tempVar = 0;
            if (this.lcdIsOn) {
                //If the LCD is enabled, then predict the LCD IRQs enabled:
                if ((this.interruptsEnabled & GBEMU_0x1) === GBEMU_0x1) {
                    currentClocks = (GBEMU_456 * ((this.modeSTAT === 1 ? GBEMU_298 : GBEMU_144) - this.actualScanLine) - this.lcdTicks) << this.doubleSpeedShifter;
                }
                if ((this.interruptsEnabled & GBEMU_0x2) === GBEMU_0x2) {
                    if (this.mode0TriggerSTAT) {
                        tempVar = (this.clocksUntilMode0() - this.lcdTicks) << this.doubleSpeedShifter;
                        if (tempVar <= currentClocks || currentClocks === -1) {
                            currentClocks = tempVar;
                        }
                    }
                    if (this.mode1TriggerSTAT && (this.interruptsEnabled & GBEMU_0x1) === 0) {
                        tempVar = (GBEMU_456 * ((this.modeSTAT === 1 ? GBEMU_298 : GBEMU_144) - this.actualScanLine) - this.lcdTicks) << this.doubleSpeedShifter;
                        if (tempVar <= currentClocks || currentClocks === -1) {
                            currentClocks = tempVar;
                        }
                    }
                    if (this.mode2TriggerSTAT) {
                        tempVar =
                            ((this.actualScanLine >= GBEMU_143 ? GBEMU_456 * (GBEMU_154 - this.actualScanLine) : GBEMU_456) - this.lcdTicks) << this.doubleSpeedShifter;
                        if (tempVar <= currentClocks || currentClocks === -1) {
                            currentClocks = tempVar;
                        }
                    }
                    if (this.lycMatchTriggerSTAT && this.memory[GBEMU_0xFF45] <= GBEMU_153) {
                        tempVar = (this.clocksUntilLYCMatch() - this.lcdTicks) << this.doubleSpeedShifter;
                        if (tempVar <= currentClocks || currentClocks === -1) {
                            currentClocks = tempVar;
                        }
                    }
                }
            }
            if (this.timaEnabled && (this.interruptsEnabled & GBEMU_0x4) === GBEMU_0x4) {
                //CPU timer IRQ prediction:
                tempVar = (GBEMU_0x100 - this.memory[GBEMU_0xFF05]) * this.tacClocker - this.timerTicks;
                if (tempVar <= currentClocks || currentClocks === -1) {
                    currentClocks = tempVar;
                }
            }
            if (this.serialTimer > 0 && (this.interruptsEnabled & GBEMU_0x8) === GBEMU_0x8) {
                //Serial IRQ prediction:
                if (this.serialTimer <= currentClocks || currentClocks === -1) {
                    currentClocks = this.serialTimer;
                }
            }
        }
        else {
            currentClocks = this.remainingClocks;
        }
        let maxClocks = (this.cpuCyclesTotal - this.emulatorTicks) << this.doubleSpeedShifter;
        if (currentClocks >= GBEMU_0) {
            if (currentClocks <= maxClocks) {
                this.cpuTicks = Math.max(currentClocks, this.cpuTicks);
                this.updateCoreFull();
                this.halt = false;
                this.cpuTicks = GBEMU_0;
            }
            else {
                this.cpuTicks = Math.max(maxClocks, this.cpuTicks);
                this.remainingClocks = currentClocks - this.cpuTicks;
            }
        }
        else {
            this.cpuTicks += maxClocks;
        }
    }
    //Memory Reading:
    memoryRead(address) {
        //Act as a wrapper for reading the returns from the compiled jumps to memory.
        return this.memoryReader[address](this, address); //This seems to be faster than the usual if/else.
    }
    memoryHighRead(address) {
        //Act as a wrapper for reading the returns from the compiled jumps to memory.
        return this.memoryHighReader[address](this, address); //This seems to be faster than the usual if/else.
    }
    memoryReadJumpCompile() {
        //debugLog('This is memoryReadJumpCompile');
        //Faster in some browsers, since we are doing less conditionals overall by implementing them in advance.
        for (let index = GBEMU_0x0000; index <= GBEMU_0xFFFF; index++) {
            if (index < GBEMU_0x4000) {
                this.memoryReader[index] = this.memoryReadNormal;
            }
            else if (index < GBEMU_0x8000) {
                this.memoryReader[index] = this.memoryReadrom;
            }
            else if (index < GBEMU_0x9800) {
                this.memoryReader[index] = this.cGBC ? this.vRAMDATAReadCGBCPU : this.vRAMDATAReadDMGCPU;
            }
            else if (index < GBEMU_0xA000) {
                this.memoryReader[index] = this.cGBC ? this.vRAMCHRReadCGBCPU : this.vRAMCHRReadDMGCPU;
            }
            else if (index >= GBEMU_0xA000 && index < GBEMU_0xC000) {
                if ((this.numRamBanks === 1 / GBEMU_16 && index < GBEMU_0xA200) || this.numRamBanks >= 1) {
                    if (this.cMBC7) {
                        this.memoryReader[index] = this.memoryReadMBC7;
                    }
                    else if (!this.cMBC3) {
                        this.memoryReader[index] = this.memoryReadMBC;
                    }
                    else {
                        this.memoryReader[index] = this.memoryReadMBC3; //MBC3 RTC + RAM
                    }
                }
                else {
                    this.memoryReader[index] = this.memoryReadBAD;
                }
            }
            else if (index >= GBEMU_0xC000 && index < GBEMU_0xE000) {
                if (!this.cGBC || index < GBEMU_0xD000) {
                    this.memoryReader[index] = this.memoryReadNormal;
                }
                else {
                    this.memoryReader[index] = this.memoryReadgbcMemory;
                }
            }
            else if (index >= GBEMU_0xE000 && index < GBEMU_0xFE00) {
                if (!this.cGBC || index < GBEMU_0xF000) {
                    this.memoryReader[index] = this.memoryReadECHONormal;
                }
                else {
                    this.memoryReader[index] = this.memoryReadECHOgbcMemory;
                }
            }
            else if (index < GBEMU_0xFEA0) {
                this.memoryReader[index] = this.memoryReadOAM;
            }
            else if (this.cGBC && index >= GBEMU_0xFEA0 && index < GBEMU_0xFF00) {
                this.memoryReader[index] = this.memoryReadNormal;
            }
            else if (index >= GBEMU_0xFF00) {
                switch (index) {
                    case GBEMU_0xFF00:
                        //JOYPAD:
                        this.memoryReader[GBEMU_0xFF00] = (parentObj, address) => {
                            return GBEMU_0xC0 | parentObj.memory[GBEMU_0xFF00]; //Top nibble returns as set.
                        };
                        this.memoryHighReader[0] = this.memoryReader[GBEMU_0xFF00];
                        break;
                    case GBEMU_0xFF01:
                        //SB
                        this.memoryReader[GBEMU_0xFF01] = (parentObj, address) => {
                            return parentObj.memory[GBEMU_0xFF02] < GBEMU_0x80 ? parentObj.memory[GBEMU_0xFF01] : GBEMU_0xFF;
                        };
                        this.memoryHighReader[GBEMU_0x01] = this.memoryReader[GBEMU_0xFF01];
                        break;
                    case GBEMU_0xFF02:
                        //SC
                        if (this.cGBC) {
                            this.memoryReader[GBEMU_0xFF02] = (parentObj, address) => {
                                return (parentObj.serialTimer <= 0 ? GBEMU_0x7C : GBEMU_0xFC) | parentObj.memory[GBEMU_0xFF02];
                            };
                            this.memoryHighReader[GBEMU_0x02] = this.memoryReader[GBEMU_0xFF02];
                        }
                        else {
                            this.memoryReader[GBEMU_0xFF02] = (parentObj, address) => {
                                return (parentObj.serialTimer <= 0 ? GBEMU_0x7E : GBEMU_0xFE) | parentObj.memory[GBEMU_0xFF02];
                            };
                            this.memoryHighReader[GBEMU_0x02] = this.memoryReader[GBEMU_0xFF02];
                        }
                        break;
                    case GBEMU_0xFF04:
                        //DIV
                        this.memoryReader[GBEMU_0xFF04] = (parentObj, address) => {
                            parentObj.memory[GBEMU_0xFF04] = (parentObj.memory[GBEMU_0xFF04] + (parentObj.divTicks >> GBEMU_8)) & GBEMU_0xFF;
                            parentObj.divTicks &= GBEMU_0xFF;
                            return parentObj.memory[GBEMU_0xFF04];
                        };
                        this.memoryHighReader[GBEMU_0x04] = this.memoryReader[GBEMU_0xFF04];
                        break;
                    case GBEMU_0xFF07:
                        this.memoryReader[GBEMU_0xFF07] = (parentObj, address) => {
                            return GBEMU_0xF8 | parentObj.memory[GBEMU_0xFF07];
                        };
                        this.memoryHighReader[GBEMU_0x07] = this.memoryReader[GBEMU_0xFF07];
                        break;
                    case GBEMU_0xFF0F:
                        //IF
                        this.memoryReader[GBEMU_0xFF0F] = (parentObj, address) => {
                            return GBEMU_0xE0 | parentObj.interruptsRequested;
                        };
                        this.memoryHighReader[GBEMU_0x0F] = this.memoryReader[GBEMU_0xFF0F];
                        break;
                    case GBEMU_0xFF10:
                        this.memoryReader[GBEMU_0xFF10] = (parentObj, address) => {
                            return GBEMU_0x80 | parentObj.memory[GBEMU_0xFF10];
                        };
                        this.memoryHighReader[GBEMU_0x10] = this.memoryReader[GBEMU_0xFF10];
                        break;
                    case GBEMU_0xFF11:
                        this.memoryReader[GBEMU_0xFF11] = (parentObj, address) => {
                            return GBEMU_0x3F | parentObj.memory[GBEMU_0xFF11];
                        };
                        this.memoryHighReader[GBEMU_0x11] = this.memoryReader[GBEMU_0xFF11];
                        break;
                    case GBEMU_0xFF13:
                        this.memoryHighReader[GBEMU_0x13] = this.memoryReadBAD;
                        this.memoryReader[GBEMU_0xFF13] = this.memoryReadBAD;
                        break;
                    case GBEMU_0xFF14:
                        this.memoryReader[GBEMU_0xFF14] = (parentObj, address) => {
                            return GBEMU_0xBF | parentObj.memory[GBEMU_0xFF14];
                        };
                        this.memoryHighReader[GBEMU_0x14] = this.memoryReader[GBEMU_0xFF14];
                        break;
                    case GBEMU_0xFF16:
                        this.memoryReader[GBEMU_0xFF16] = (parentObj, address) => {
                            return GBEMU_0x3F | parentObj.memory[GBEMU_0xFF16];
                        };
                        this.memoryHighReader[GBEMU_0x16] = this.memoryReader[GBEMU_0xFF16];
                        break;
                    case GBEMU_0xFF18:
                        this.memoryHighReader[GBEMU_0x18] = this.memoryReadBAD;
                        this.memoryReader[GBEMU_0xFF18] = this.memoryReadBAD;
                        break;
                    case GBEMU_0xFF19:
                        this.memoryReader[GBEMU_0xFF19] = (parentObj, address) => {
                            return GBEMU_0xBF | parentObj.memory[GBEMU_0xFF19];
                        };
                        this.memoryHighReader[GBEMU_0x19] = this.memoryReader[GBEMU_0xFF19];
                        break;
                    case GBEMU_0xFF1A:
                        this.memoryReader[GBEMU_0xFF1A] = (parentObj, address) => {
                            return GBEMU_0x7F | parentObj.memory[GBEMU_0xFF1A];
                        };
                        this.memoryHighReader[GBEMU_0x1A] = this.memoryReader[GBEMU_0xFF1A];
                        break;
                    case GBEMU_0xFF1B:
                        this.memoryHighReader[GBEMU_0x1B] = this.memoryReadBAD;
                        this.memoryReader[GBEMU_0xFF1B] = this.memoryReadBAD;
                        break;
                    case GBEMU_0xFF1C:
                        this.memoryReader[GBEMU_0xFF1C] = (parentObj, address) => {
                            return GBEMU_0x9F | parentObj.memory[GBEMU_0xFF1C];
                        };
                        this.memoryHighReader[GBEMU_0x1C] = this.memoryReader[GBEMU_0xFF1C];
                        break;
                    case GBEMU_0xFF1D:
                        this.memoryReader[GBEMU_0xFF1D] = (parentObj, address) => {
                            return GBEMU_0xFF;
                        };
                        this.memoryHighReader[GBEMU_0x1D] = this.memoryReader[GBEMU_0xFF1D];
                        break;
                    case GBEMU_0xFF1E:
                        this.memoryReader[GBEMU_0xFF1E] = (parentObj, address) => {
                            return GBEMU_0xBF | parentObj.memory[GBEMU_0xFF1E];
                        };
                        this.memoryHighReader[GBEMU_0x1E] = this.memoryReader[GBEMU_0xFF1E];
                        break;
                    case GBEMU_0xFF1F:
                    case GBEMU_0xFF20:
                        this.memoryHighReader[index & GBEMU_0xFF] = this.memoryReadBAD;
                        this.memoryReader[index] = this.memoryReadBAD;
                        break;
                    case GBEMU_0xFF23:
                        this.memoryReader[GBEMU_0xFF23] = (parentObj, address) => {
                            return GBEMU_0xBF | parentObj.memory[GBEMU_0xFF23];
                        };
                        this.memoryHighReader[GBEMU_0x23] = this.memoryReader[GBEMU_0xFF23];
                        break;
                    case GBEMU_0xFF26:
                        this.memoryReader[GBEMU_0xFF26] = (parentObj, address) => {
                            parentObj.audioJIT();
                            return GBEMU_0x70 | parentObj.memory[GBEMU_0xFF26];
                        };
                        this.memoryHighReader[GBEMU_0x26] = this.memoryReader[GBEMU_0xFF26];
                        break;
                    case GBEMU_0xFF27:
                    case GBEMU_0xFF28:
                    case GBEMU_0xFF29:
                    case GBEMU_0xFF2A:
                    case GBEMU_0xFF2B:
                    case GBEMU_0xFF2C:
                    case GBEMU_0xFF2D:
                    case GBEMU_0xFF2E:
                    case GBEMU_0xFF2F:
                        this.memoryReader[index] = this.memoryReadBAD;
                        this.memoryHighReader[index & GBEMU_0xFF] = this.memoryReader[index];
                        break;
                    case GBEMU_0xFF30:
                    case GBEMU_0xFF31:
                    case GBEMU_0xFF32:
                    case GBEMU_0xFF33:
                    case GBEMU_0xFF34:
                    case GBEMU_0xFF35:
                    case GBEMU_0xFF36:
                    case GBEMU_0xFF37:
                    case GBEMU_0xFF38:
                    case GBEMU_0xFF39:
                    case GBEMU_0xFF3A:
                    case GBEMU_0xFF3B:
                    case GBEMU_0xFF3C:
                    case GBEMU_0xFF3D:
                    case GBEMU_0xFF3E:
                    case GBEMU_0xFF3F:
                        this.memoryReader[index] = (parentObj, address) => {
                            return parentObj.channel3canPlay ? parentObj.memory[GBEMU_0xFF00 | (parentObj.channel3lastSampleLookup >> 1)] : parentObj.memory[address];
                        };
                        this.memoryHighReader[index & GBEMU_0xFF] = (parentObj, address) => {
                            return parentObj.channel3canPlay ?
                                parentObj.memory[GBEMU_0xFF00 | (parentObj.channel3lastSampleLookup >> 1)] :
                                parentObj.memory[GBEMU_0xFF00 | address];
                        };
                        break;
                    case GBEMU_0xFF41:
                        this.memoryReader[GBEMU_0xFF41] = (parentObj, address) => {
                            return GBEMU_0x80 | parentObj.memory[GBEMU_0xFF41] | parentObj.modeSTAT;
                        };
                        this.memoryHighReader[GBEMU_0x41] = this.memoryReader[GBEMU_0xFF41];
                        break;
                    case GBEMU_0xFF42:
                        this.memoryReader[GBEMU_0xFF42] = (parentObj, address) => {
                            return parentObj.backgroundY;
                        };
                        this.memoryHighReader[GBEMU_0x42] = this.memoryReader[GBEMU_0xFF42];
                        break;
                    case GBEMU_0xFF43:
                        this.memoryReader[GBEMU_0xFF43] = (parentObj, address) => {
                            return parentObj.backgroundX;
                        };
                        this.memoryHighReader[GBEMU_0x43] = this.memoryReader[GBEMU_0xFF43];
                        break;
                    case GBEMU_0xFF44:
                        this.memoryReader[GBEMU_0xFF44] = (parentObj, address) => {
                            return parentObj.lcdIsOn ? parentObj.memory[GBEMU_0xFF44] : 0;
                        };
                        this.memoryHighReader[GBEMU_0x44] = this.memoryReader[GBEMU_0xFF44];
                        break;
                    case GBEMU_0xFF4A:
                        //WY
                        this.memoryReader[GBEMU_0xFF4A] = (parentObj, address) => {
                            return parentObj.windowY;
                        };
                        this.memoryHighReader[GBEMU_0x4A] = this.memoryReader[GBEMU_0xFF4A];
                        break;
                    case GBEMU_0xFF4F:
                        this.memoryReader[GBEMU_0xFF4F] = (parentObj, address) => {
                            return parentObj.currvramBank;
                        };
                        this.memoryHighReader[GBEMU_0x4F] = this.memoryReader[GBEMU_0xFF4F];
                        break;
                    case GBEMU_0xFF55:
                        if (this.cGBC) {
                            this.memoryReader[GBEMU_0xFF55] = (parentObj, address) => {
                                if (!parentObj.lcdIsOn && parentObj.hdmaRunning) {
                                    //Undocumented behavior alert: HDMA becomes GDMA when LCD is oFF (Worms Armageddon Fix).
                                    //DMA
                                    parentObj.dMAWrite((parentObj.memory[GBEMU_0xFF55] & GBEMU_0x7f) + 1);
                                    parentObj.memory[GBEMU_0xFF55] = GBEMU_0xFF; //Transfer completed.
                                    parentObj.hdmaRunning = false;
                                }
                                return parentObj.memory[GBEMU_0xFF55];
                            };
                            this.memoryHighReader[GBEMU_0x55] = this.memoryReader[GBEMU_0xFF55];
                        }
                        else {
                            this.memoryReader[GBEMU_0xFF55] = this.memoryReadNormal;
                            this.memoryHighReader[GBEMU_0x55] = this.memoryHighReadNormal;
                        }
                        break;
                    case GBEMU_0xFF56:
                        if (this.cGBC) {
                            this.memoryReader[GBEMU_0xFF56] = (parentObj, address) => {
                                //Return IR 'not connected' status:
                                return (GBEMU_0x3C |
                                    (parentObj.memory[GBEMU_0xFF56] >= GBEMU_0xC0 ?
                                        GBEMU_0x2 | (parentObj.memory[GBEMU_0xFF56] & GBEMU_0xC1) :
                                        parentObj.memory[GBEMU_0xFF56] & GBEMU_0xC3));
                            };
                            this.memoryHighReader[GBEMU_0x56] = this.memoryReader[GBEMU_0xFF56];
                        }
                        else {
                            this.memoryReader[GBEMU_0xFF56] = this.memoryReadNormal;
                            this.memoryHighReader[GBEMU_0x56] = this.memoryHighReadNormal;
                        }
                        break;
                    case GBEMU_0xFF6C:
                        if (this.cGBC) {
                            this.memoryReader[GBEMU_0xFF6C] = (parentObj, address) => {
                                return GBEMU_0xFE | parentObj.memory[GBEMU_0xFF6C];
                            };
                            this.memoryHighReader[GBEMU_0x6c] = this.memoryReader[GBEMU_0xFF6C];
                        }
                        else {
                            this.memoryReader[GBEMU_0xFF6C] = this.memoryReadBAD;
                            this.memoryHighReader[GBEMU_0x6C] = this.memoryReadBAD;
                        }
                        break;
                    case GBEMU_0xFF70:
                        if (this.cGBC) {
                            //SVBK
                            this.memoryReader[GBEMU_0xFF70] = (parentObj, address) => {
                                return GBEMU_0x40 | parentObj.memory[GBEMU_0xFF70];
                            };
                            this.memoryHighReader[GBEMU_0x70] = this.memoryReader[GBEMU_0xFF70];
                        }
                        else {
                            this.memoryReader[GBEMU_0xFF70] = this.memoryReadBAD;
                            this.memoryHighReader[GBEMU_0x70] = this.memoryReadBAD;
                        }
                        break;
                    case GBEMU_0xFF75:
                        this.memoryReader[GBEMU_0xFF75] = (parentObj, address) => {
                            return GBEMU_0x8F | parentObj.memory[GBEMU_0xFF75];
                        };
                        this.memoryHighReader[GBEMU_0x75] = this.memoryReader[GBEMU_0xFF75];
                        break;
                    case GBEMU_0xFF76:
                    case GBEMU_0xFF77:
                        this.memoryReader[index] = (parentObj, address) => {
                            return 0;
                        };
                        this.memoryHighReader[index & GBEMU_0xFF] = this.memoryReader[index];
                        break;
                    case GBEMU_0xFFFF:
                        //IE
                        this.memoryReader[GBEMU_0xFFFF] = (parentObj, address) => {
                            return parentObj.interruptsEnabled;
                        };
                        this.memoryHighReader[GBEMU_0xFF] = this.memoryReader[GBEMU_0xFFFF];
                        break;
                    default:
                        this.memoryReader[index] = this.memoryReadNormal;
                        this.memoryHighReader[index & GBEMU_0xFF] = this.memoryHighReadNormal;
                }
            }
            else {
                this.memoryReader[index] = this.memoryReadBAD;
            }
        }
    }
    memoryReadNormal(parentObj, address) {
        return parentObj.memory[address];
    }
    memoryHighReadNormal(parentObj, address) {
        return parentObj.memory[GBEMU_0xFF00 | address];
    }
    memoryReadrom(parentObj, address) {
        return parentObj.rom[parentObj.currentromBank + address];
    }
    memoryReadMBC(parentObj, address) {
        //Switchable RAM
        if (parentObj.mbcRamBanksEnabled || settings[GBEMU_10]) {
            return parentObj.mbcRam[address + parentObj.currMBCRAMBankPosition];
        }
        //cout('Reading from disabled RAM.', 1);
        return GBEMU_0xFF;
    }
    memoryReadMBC7(parentObj, address) {
        //debugLog('This is memoryReadMBC7');
        //Switchable RAM
        if (parentObj.mbcRamBanksEnabled || settings[GBEMU_10]) {
            switch (address) {
                case GBEMU_0xA000:
                case GBEMU_0xA060:
                case GBEMU_0xA070:
                    return 0;
                case GBEMU_0xA080:
                    //TODO: Gyro Control Register
                    return 0;
                case GBEMU_0xA050:
                    //Y High Byte
                    return parentObj.highY;
                case GBEMU_0xA040:
                    //Y Low Byte
                    return parentObj.lowY;
                case GBEMU_0xA030:
                    //X High Byte
                    return parentObj.highX;
                case GBEMU_0xA020:
                    //X Low Byte:
                    return parentObj.lowX;
                default:
                    return parentObj.mbcRam[address + parentObj.currMBCRAMBankPosition];
            }
        }
        //cout('Reading from disabled RAM.', 1);
        return GBEMU_0xFF;
    }
    memoryReadMBC3(parentObj, address) {
        //debugLog('This is memoryReadMBC3');
        //Switchable RAM
        if (parentObj.mbcRamBanksEnabled || settings[GBEMU_10]) {
            switch (parentObj.currMBCRAMBank) {
                case GBEMU_0x00:
                case GBEMU_0x01:
                case GBEMU_0x02:
                case GBEMU_0x03:
                    return parentObj.mbcRam[address + parentObj.currMBCRAMBankPosition];
                case GBEMU_0x08:
                    return parentObj.latchedSeconds;
                case GBEMU_0x09:
                    return parentObj.latchedMinutes;
                case GBEMU_0x0A:
                    return parentObj.latchedHours;
                case GBEMU_0x0B:
                    return parentObj.latchedLDays;
                case GBEMU_0x0C:
                    return (parentObj.rtcDayOverFlow ? GBEMU_0x80 : 0) + (parentObj.rtcHalt ? GBEMU_0x40 : 0) + parentObj.latchedHDays;
                default:
                    return 0;
            }
        }
        //cout('Reading from invalid or disabled RAM.', 1);
        return GBEMU_0xFF;
    }
    memoryReadgbcMemory(parentObj, address) {
        return parentObj.gbcMemory[address + parentObj.gbcRamBankPosition];
    }
    memoryReadOAM(parentObj, address) {
        return parentObj.modeSTAT > 1 ? GBEMU_0xFF : parentObj.memory[address];
    }
    memoryReadECHOgbcMemory(parentObj, address) {
        return parentObj.gbcMemory[address + parentObj.gbcRamBankPositionECHO];
    }
    memoryReadECHONormal(parentObj, address) {
        return parentObj.memory[address - GBEMU_0x2000];
    }
    memoryReadBAD(parentObj, address) {
        return GBEMU_0xFF;
    }
    vRAMDATAReadCGBCPU(parentObj, address) {
        //CPU Side Reading The vram (Optimized for GameBoy Color)
        return parentObj.modeSTAT > GBEMU_2 ? GBEMU_0xFF : parentObj.currvramBank === 0 ? parentObj.memory[address] : parentObj.vram[address & GBEMU_0x1fff];
    }
    vRAMDATAReadDMGCPU(parentObj, address) {
        //CPU Side Reading The vram (Optimized for classic GameBoy)
        return parentObj.modeSTAT > GBEMU_2 ? GBEMU_0xFF : parentObj.memory[address];
    }
    vRAMCHRReadCGBCPU(parentObj, address) {
        //CPU Side Reading the Character Data Map:
        return parentObj.modeSTAT > GBEMU_2 ? GBEMU_0xFF : parentObj.bgCHRCurrentBank.array[address & GBEMU_0x7FF];
    }
    vRAMCHRReadDMGCPU(parentObj, address) {
        //CPU Side Reading the Character Data Map:
        return parentObj.modeSTAT > GBEMU_2 ? GBEMU_0xFF : parentObj.bgCHRBank1.array[address & GBEMU_0x7FF];
    }
    setCurrentMBC1romBank() {
        //debugLog('This is setCurrentMBC1romBank');
        //Read the cartridge rom data from RAM memory:
        switch (this.romBank1offs) {
            case GBEMU_0x00:
            case GBEMU_0x20:
            case GBEMU_0x40:
            case GBEMU_0x60:
                //Bank calls for 0x00, 0x20, 0x40, and 0x60 are really for 0x01, 0x21, 0x41, and 0x61.
                this.currentromBank = this.romBank1offs % this.romBankEdge << GBEMU_14;
                break;
            default:
                this.currentromBank = ((this.romBank1offs % this.romBankEdge) - 1) << GBEMU_14;
        }
    }
    setCurrentMBC2AND3romBank() {
        //Read the cartridge rom data from RAM memory:
        //Only map bank 0 to bank 1 here (MBC2 is like MBC1, but can only do GBEMU_16 banks, so only the bank 0 quirk appears for MBC2):
        this.currentromBank = Math.max((this.romBank1offs % this.romBankEdge) - 1, 0) << GBEMU_14;
    }
    setCurrentMBC5romBank() {
        //Read the cartridge rom data from RAM memory:
        this.currentromBank = ((this.romBank1offs % this.romBankEdge) - 1) << GBEMU_14;
    }
    //Memory Writing:
    memoryWrite(address, data) {
        //Act as a wrapper for writing by compiled jumps to specific memory writing functions.
        this.memoryWriter[address](this, address, data);
    }
    //0xFFXX fast path:
    memoryHighWrite(address, data) {
        //Act as a wrapper for writing by compiled jumps to specific memory writing functions.
        this.memoryHighWriter[address](this, address, data);
    }
    memoryWriteJumpCompile() {
        //debugLog('This is memoryWriteJumpCompile');
        //Faster in some browsers, since we are doing less conditionals overall by implementing them in advance.
        for (let index = GBEMU_0x0000; index <= GBEMU_0xFFFF; index++) {
            if (index < GBEMU_0x8000) {
                if (this.cMBC1) {
                    if (index < GBEMU_0x2000) {
                        this.memoryWriter[index] = this.mBCWriteEnable;
                    }
                    else if (index < GBEMU_0x4000) {
                        this.memoryWriter[index] = this.mBC1WriteromBank;
                    }
                    else if (index < GBEMU_0x6000) {
                        this.memoryWriter[index] = this.mBC1WriteRAMBank;
                    }
                    else {
                        this.memoryWriter[index] = this.mBC1WriteType;
                    }
                }
                else if (this.cMBC2) {
                    if (index < GBEMU_0x1000) {
                        this.memoryWriter[index] = this.mBCWriteEnable;
                    }
                    else if (index >= GBEMU_0x2100 && index < GBEMU_0x2200) {
                        this.memoryWriter[index] = this.mBC2WriteromBank;
                    }
                    else {
                        this.memoryWriter[index] = this.cartIgnoreWrite;
                    }
                }
                else if (this.cMBC3) {
                    if (index < GBEMU_0x2000) {
                        this.memoryWriter[index] = this.mBCWriteEnable;
                    }
                    else if (index < GBEMU_0x4000) {
                        this.memoryWriter[index] = this.mBC3WriteromBank;
                    }
                    else if (index < GBEMU_0x6000) {
                        this.memoryWriter[index] = this.mBC3WriteRAMBank;
                    }
                    else {
                        this.memoryWriter[index] = this.mBC3WriteRTCLatch;
                    }
                }
                else if (this.cMBC5 || this.cRUMBLE || this.cMBC7) {
                    if (index < GBEMU_0x2000) {
                        this.memoryWriter[index] = this.mBCWriteEnable;
                    }
                    else if (index < GBEMU_0x3000) {
                        this.memoryWriter[index] = this.mBC5WriteromBankLow;
                    }
                    else if (index < GBEMU_0x4000) {
                        this.memoryWriter[index] = this.mBC5WriteromBankHigh;
                    }
                    else if (index < GBEMU_0x6000) {
                        this.memoryWriter[index] = this.cRUMBLE ? this.rUMBLEWriteRAMBank : this.mBC5WriteRAMBank;
                    }
                    else {
                        this.memoryWriter[index] = this.cartIgnoreWrite;
                    }
                }
                else if (this.cHuC3) {
                    if (index < GBEMU_0x2000) {
                        this.memoryWriter[index] = this.mBCWriteEnable;
                    }
                    else if (index < GBEMU_0x4000) {
                        this.memoryWriter[index] = this.mBC3WriteromBank;
                    }
                    else if (index < GBEMU_0x6000) {
                        this.memoryWriter[index] = this.huC3WriteRAMBank;
                    }
                    else {
                        this.memoryWriter[index] = this.cartIgnoreWrite;
                    }
                }
                else {
                    this.memoryWriter[index] = this.cartIgnoreWrite;
                }
            }
            else if (index < GBEMU_0x9000) {
                this.memoryWriter[index] = this.cGBC ? this.vRAMGBCDATAWrite : this.vRAMGBDATAWrite;
            }
            else if (index < GBEMU_0x9800) {
                this.memoryWriter[index] = this.cGBC ? this.vRAMGBCDATAWrite : this.vRAMGBDATAUpperWrite;
            }
            else if (index < GBEMU_0xA000) {
                this.memoryWriter[index] = this.cGBC ? this.vRAMGBCCHRMAPWrite : this.vRAMGBCHRMAPWrite;
            }
            else if (index < GBEMU_0xC000) {
                if ((this.numRamBanks === 1 / GBEMU_16 && index < GBEMU_0xA200) || this.numRamBanks >= 1) {
                    if (!this.cMBC3) {
                        this.memoryWriter[index] = this.memoryWriteMBCRAM;
                    }
                    else {
                        this.memoryWriter[index] = this.memoryWriteMBC3RAM; //MBC3 RTC + RAM
                    }
                }
                else {
                    this.memoryWriter[index] = this.cartIgnoreWrite;
                }
            }
            else if (index < GBEMU_0xE000) {
                if (this.cGBC && index >= GBEMU_0xD000) {
                    this.memoryWriter[index] = this.memoryWriteGBCRAM;
                }
                else {
                    this.memoryWriter[index] = this.memoryWriteNormal;
                }
            }
            else if (index < GBEMU_0xFE00) {
                if (this.cGBC && index >= GBEMU_0xF000) {
                    this.memoryWriter[index] = this.memoryWriteECHOGBCRAM;
                }
                else {
                    this.memoryWriter[index] = this.memoryWriteECHONormal;
                }
            }
            else if (index <= GBEMU_0xFEA0) {
                this.memoryWriter[index] = this.memoryWriteOAMRAM;
            }
            else if (index < GBEMU_0xFF00) {
                if (this.cGBC) {
                    //Only GBC has access to this RAM.
                    this.memoryWriter[index] = this.memoryWriteNormal;
                }
                else {
                    this.memoryWriter[index] = this.cartIgnoreWrite;
                }
            }
            else {
                this.memoryWriter[index] = this.memoryWriteNormal;
                this.memoryHighWriter[index & GBEMU_0xFF] = this.memoryHighWriteNormal;
            }
        }
        this.registerWriteJumpCompile(); //Compile the I/O write functions separately...
    }
    mBCWriteEnable(parentObj, address, data) {
        //debugLog('This is MBCWriteEnable');
        //MBC RAM Bank Enable/Disable:
        parentObj.mbcRamBanksEnabled = (data & GBEMU_0x0F) === GBEMU_0x0A; //If lower nibble is GBEMU_0x0A, then enable, otherwise disable.
    }
    mBC1WriteromBank(parentObj, address, data) {
        //debugLog('This is MBC1WriteromBank');
        //MBC1 rom bank switching:
        parentObj.romBank1offs = (parentObj.romBank1offs & GBEMU_0x60) | (data & GBEMU_0x1F);
        parentObj.setCurrentMBC1romBank();
    }
    mBC1WriteRAMBank(parentObj, address, data) {
        //MBC1 RAM bank switching
        if (parentObj.mbc1Mode) {
            //GBEMU_4/GBEMU_32 Mode
            parentObj.currMBCRAMBank = data & GBEMU_0x03;
            parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << GBEMU_13) - GBEMU_0xA000;
        }
        else {
            //GBEMU_16/GBEMU_8 Mode
            parentObj.romBank1offs = ((data & GBEMU_0x03) << GBEMU_5) | (parentObj.romBank1offs & GBEMU_0x1F);
            parentObj.setCurrentMBC1romBank();
        }
    }
    mBC1WriteType(parentObj, address, data) {
        //MBC1 mode setting:
        parentObj.mbc1Mode = (data & GBEMU_0x1) === GBEMU_0x1;
        if (parentObj.mbc1Mode) {
            parentObj.romBank1offs &= GBEMU_0x1F;
            parentObj.setCurrentMBC1romBank();
        }
        else {
            parentObj.currMBCRAMBank = 0;
            parentObj.currMBCRAMBankPosition = -GBEMU_0xA000;
        }
    }
    mBC2WriteromBank(parentObj, address, data) {
        //MBC2 rom bank switching:
        parentObj.romBank1offs = data & GBEMU_0x0F;
        parentObj.setCurrentMBC2AND3romBank();
    }
    mBC3WriteromBank(parentObj, address, data) {
        //MBC3 rom bank switching:
        parentObj.romBank1offs = data & GBEMU_0x7F;
        parentObj.setCurrentMBC2AND3romBank();
    }
    mBC3WriteRAMBank(parentObj, address, data) {
        parentObj.currMBCRAMBank = data;
        if (data < GBEMU_4) {
            //MBC3 RAM bank switching
            parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << GBEMU_13) - GBEMU_0xA000;
        }
    }
    mBC3WriteRTCLatch(parentObj, address, data) {
        if (data === 0) {
            parentObj.rtcIsLatched = false;
        }
        else if (!parentObj.rtcIsLatched) {
            //Copy over the current RTC time for reading.
            parentObj.rtcIsLatched = true;
            parentObj.latchedSeconds = parentObj.rtcSeconds | GBEMU_0;
            parentObj.latchedMinutes = parentObj.rtcMinutes;
            parentObj.latchedHours = parentObj.rtcHours;
            parentObj.latchedLDays = parentObj.rtcDays & GBEMU_0xFF;
            parentObj.latchedHDays = parentObj.rtcDays >> GBEMU_8;
        }
    }
    mBC5WriteromBankLow(parentObj, address, data) {
        //MBC5 rom bank switching:
        parentObj.romBank1offs = (parentObj.romBank1offs & GBEMU_0x100) | data;
        parentObj.setCurrentMBC5romBank();
    }
    mBC5WriteromBankHigh(parentObj, address, data) {
        //MBC5 rom bank switching (by least significant bit):
        parentObj.romBank1offs = ((data & GBEMU_0x01) << GBEMU_8) | (parentObj.romBank1offs & GBEMU_0xFF);
        parentObj.setCurrentMBC5romBank();
    }
    mBC5WriteRAMBank(parentObj, address, data) {
        //MBC5 RAM bank switching
        parentObj.currMBCRAMBank = data & GBEMU_0xF;
        parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << GBEMU_13) - GBEMU_0xA000;
    }
    rUMBLEWriteRAMBank(parentObj, address, data) {
        //MBC5 RAM bank switching
        //Like MBC5, but bit GBEMU_3 of the lower nibble is used for rumbling and bit GBEMU_2 is ignored.
        parentObj.currMBCRAMBank = data & GBEMU_0x03;
        parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << GBEMU_13) - GBEMU_0xA000;
    }
    huC3WriteRAMBank(parentObj, address, data) {
        //HuC3 RAM bank switching
        parentObj.currMBCRAMBank = data & GBEMU_0x03;
        parentObj.currMBCRAMBankPosition = (parentObj.currMBCRAMBank << GBEMU_13) - GBEMU_0xA000;
    }
    cartIgnoreWrite(parentObj, address, data) {
        //We might have encountered illegal RAM writing or such, so just do nothing...
    }
    memoryWriteNormal(parentObj, address, data) {
        parentObj.memory[address] = data;
    }
    memoryHighWriteNormal(parentObj, address, data) {
        parentObj.memory[GBEMU_0xFF00 | address] = data;
    }
    memoryWriteMBCRAM(parentObj, address, data) {
        if (parentObj.mbcRamBanksEnabled || settings[GBEMU_10]) {
            parentObj.mbcRam[address + parentObj.currMBCRAMBankPosition] = data;
        }
    }
    memoryWriteMBC3RAM(parentObj, address, data) {
        //debugLog('This is memoryWriteMBC3RAM');
        if (parentObj.mbcRamBanksEnabled || settings[GBEMU_10]) {
            switch (parentObj.currMBCRAMBank) {
                case GBEMU_0x00:
                case GBEMU_0x01:
                case GBEMU_0x02:
                case GBEMU_0x03:
                    parentObj.mbcRam[address + parentObj.currMBCRAMBankPosition] = data;
                    break;
                case GBEMU_0x08:
                    if (data < GBEMU_60) {
                        parentObj.rtcSeconds = data;
                    }
                    else {
                        cout('(Bank #' + parentObj.currMBCRAMBank + ') RTC write out of range: ' + data, 1);
                    }
                    break;
                case GBEMU_0x09:
                    if (data < GBEMU_60) {
                        parentObj.rtcMinutes = data;
                    }
                    else {
                        cout('(Bank #' + parentObj.currMBCRAMBank + ') RTC write out of range: ' + data, 1);
                    }
                    break;
                case GBEMU_0x0A:
                    if (data < GBEMU_24) {
                        parentObj.rtcHours = data;
                    }
                    else {
                        cout('(Bank #' + parentObj.currMBCRAMBank + ') RTC write out of range: ' + data, 1);
                    }
                    break;
                case GBEMU_0x0B:
                    parentObj.rtcDays = (data & GBEMU_0xFF) | (parentObj.rtcDays & GBEMU_0x100);
                    break;
                case GBEMU_0x0C:
                    parentObj.rtcDayOverFlow = data > GBEMU_0x7F;
                    parentObj.rtcHalt = (data & GBEMU_0x40) === GBEMU_0x40;
                    parentObj.rtcDays = ((data & GBEMU_0x1) << GBEMU_8) | (parentObj.rtcDays & GBEMU_0xFF);
                    break;
                default:
                    cout('Invalid MBC3 bank address selected: ' + parentObj.currMBCRAMBank, 0);
            }
        }
    }
    memoryWriteGBCRAM(parentObj, address, data) {
        parentObj.gbcMemory[address + parentObj.gbcRamBankPosition] = data;
    }
    memoryWriteOAMRAM(parentObj, address, data) {
        if (parentObj.modeSTAT < GBEMU_2) {
            //OAM RAM cannot be written to in mode GBEMU_2 & GBEMU_3
            if (parentObj.memory[address] !== data) {
                parentObj.graphicsJIT();
                parentObj.memory[address] = data;
            }
        }
    }
    memoryWriteECHOGBCRAM(parentObj, address, data) {
        parentObj.gbcMemory[address + parentObj.gbcRamBankPositionECHO] = data;
    }
    memoryWriteECHONormal(parentObj, address, data) {
        parentObj.memory[address - GBEMU_0x2000] = data;
    }
    vRAMGBDATAWrite(parentObj, address, data) {
        if (parentObj.modeSTAT < GBEMU_3) {
            //vram cannot be written to during mode GBEMU_3
            if (parentObj.memory[address] !== data) {
                //JIT the graphics render queue:
                parentObj.graphicsJIT();
                parentObj.memory[address] = data;
                parentObj.generateGBOAMTileLine(address);
            }
        }
    }
    vRAMGBDATAUpperWrite(parentObj, address, data) {
        if (parentObj.modeSTAT < GBEMU_3) {
            //vram cannot be written to during mode GBEMU_3
            if (parentObj.memory[address] !== data) {
                //JIT the graphics render queue:
                parentObj.graphicsJIT();
                parentObj.memory[address] = data;
                parentObj.generateGBTileLine(address);
            }
        }
    }
    vRAMGBCDATAWrite(parentObj, addressTemp, data) {
        let address = addressTemp;
        if (parentObj.modeSTAT < GBEMU_3) {
            //vram cannot be written to during mode GBEMU_3
            if (parentObj.currvramBank === GBEMU_0) {
                if (parentObj.memory[address] !== data) {
                    parentObj.graphicsJIT(); //JIT the graphics render queue
                    parentObj.memory[address] = data;
                    parentObj.generateGBCTileLineBank1(address);
                }
            }
            else {
                address &= GBEMU_0x1FFF;
                if (parentObj.vram[address] != data) {
                    //JIT the graphics render queue:
                    parentObj.graphicsJIT();
                    parentObj.vram[address] = data;
                    parentObj.generateGBCTileLineBank2(address);
                }
            }
        }
    }
    vRAMGBCHRMAPWrite(parentObj, addressTemp, data) {
        let address = addressTemp;
        if (parentObj.modeSTAT < GBEMU_3) {
            //vram cannot be written to during mode GBEMU_3
            address &= GBEMU_0x7FF;
            if (parentObj.bgCHRBank1.array[address] !== data) {
                //JIT the graphics render queue:
                parentObj.graphicsJIT();
                parentObj.bgCHRBank1.array[address] = data;
            }
        }
    }
    vRAMGBCCHRMAPWrite(parentObj, tempAddress, data) {
        let address = tempAddress;
        if (parentObj.modeSTAT < GBEMU_3) {
            //vram cannot be written to during mode GBEMU_3
            address &= GBEMU_0x7FF;
            if (parentObj.bgCHRCurrentBank.array[address] !== data) {
                //JIT the graphics render queue:
                parentObj.graphicsJIT();
                parentObj.bgCHRCurrentBank.array[address] = data;
            }
        }
    }
    dMAWrite(tilesToTransferTemp) {
        let tilesToTransfer = tilesToTransferTemp;
        if (!this.halt) {
            //Clock the CPU for the DMA transfer (CPU is halted during the transfer):
            this.cpuTicks += GBEMU_4 | ((tilesToTransfer << GBEMU_5) << this.doubleSpeedShifter);
        }
        //Source address of the transfer:
        let source = (this.memory[GBEMU_0xFF51] << GBEMU_8) | this.memory[GBEMU_0xFF52];
        //Destination address in the vram memory range:
        let destination = (this.memory[GBEMU_0xFF53] << GBEMU_8) | this.memory[GBEMU_0xFF54];
        //Creating some references:
        let memoryReader = this.memoryReader;
        //JIT the graphics render queue:
        this.graphicsJIT();
        let memory = this.memory;
        //Determining which bank we're working on so we can optimize:
        if (this.currvramBank === 0) {
            //DMA transfer for vram bank 0:
            do {
                if (destination < GBEMU_0x1800) {
                    memory[GBEMU_0x8000 | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x8001 | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x8002 | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x8003 | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x8004 | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x8005 | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x8006 | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x8007 | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x8008 | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x8009 | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x800A | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x800B | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x800C | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x800D | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x800E | destination] = memoryReader[source](this, source++);
                    memory[GBEMU_0x800F | destination] = memoryReader[source](this, source++);
                    this.generateGBCTileBank1(destination);
                    destination += GBEMU_0x10;
                }
                else {
                    destination &= GBEMU_0x7F0;
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank1.array[destination++] = memoryReader[source](this, source++);
                    destination = (destination + GBEMU_0x1800) & GBEMU_0x1FF0;
                }
                source &= GBEMU_0xFFF0;
                tilesToTransfer -= 1;
            } while (tilesToTransfer > 0);
        }
        else {
            let vram = this.vram;
            //DMA transfer for vram bank 1:
            do {
                if (destination < GBEMU_0x1800) {
                    vram[destination] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0x1] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0x2] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0x3] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0x4] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0x5] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0x6] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0x7] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0x8] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0x9] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0xA] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0xB] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0xC] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0xD] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0xE] = memoryReader[source](this, source++);
                    vram[destination | GBEMU_0xF] = memoryReader[source](this, source++);
                    this.generateGBCTileBank2(destination);
                    destination += GBEMU_0x10;
                }
                else {
                    destination &= GBEMU_0x7F0;
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    this.bgCHRBank2.array[destination++] = memoryReader[source](this, source++);
                    destination = (destination + GBEMU_0x1800) & GBEMU_0x1FF0;
                }
                source &= GBEMU_0xFFF0;
                tilesToTransfer -= 1;
            } while (tilesToTransfer > 0);
        }
        //Update the HDMA registers to their next addresses:
        memory[GBEMU_0xFF51] = source >> GBEMU_8;
        memory[GBEMU_0xFF52] = source & GBEMU_0xF0;
        memory[GBEMU_0xFF53] = destination >> GBEMU_8;
        memory[GBEMU_0xFF54] = destination & GBEMU_0xF0;
    }
    registerWriteJumpCompile() {
        //debugLog('This is registerWriteJumpCompile');
        //I/O Registers (GB + GBC):
        //joyPad
        this.memoryWriter[GBEMU_0xFF00] = (parentObj, address, data) => {
            parentObj.memory[GBEMU_0xFF00] =
                (data & GBEMU_0x30) |
                    (((data & GBEMU_0x20) === 0 ? parentObj.joyPad >> GBEMU_4 : GBEMU_0xF) & ((data & GBEMU_0x10) === 0 ? parentObj.joyPad & GBEMU_0xF : GBEMU_0xF));
        };
        this.memoryHighWriter[0] = this.memoryWriter[GBEMU_0xFF00];
        //SB (Serial Transfer Data)
        this.memoryWriter[GBEMU_0xFF01] = (parentObj, address, data) => {
            if (parentObj.memory[GBEMU_0xFF02] < GBEMU_0x80) {
                //Cannot write while a serial transfer is active.
                parentObj.memory[GBEMU_0xFF01] = data;
            }
        };
        this.memoryHighWriter[GBEMU_0x1] = this.memoryWriter[GBEMU_0xFF01];
        //DIV
        this.memoryWriter[GBEMU_0xFF04] = (parentObj, address, data) => {
            parentObj.divTicks &= GBEMU_0xFF; //Update DIV for realignment.
            parentObj.memory[GBEMU_0xFF04] = 0;
        };
        this.memoryHighWriter[GBEMU_0x4] = this.memoryWriter[GBEMU_0xFF04];
        //TIMA
        this.memoryWriter[GBEMU_0xFF05] = (parentObj, address, data) => {
            parentObj.memory[GBEMU_0xFF05] = data;
        };
        this.memoryHighWriter[GBEMU_0x5] = this.memoryWriter[GBEMU_0xFF05];
        //TMA
        this.memoryWriter[GBEMU_0xFF06] = (parentObj, address, data) => {
            parentObj.memory[GBEMU_0xFF06] = data;
        };
        this.memoryHighWriter[GBEMU_0x6] = this.memoryWriter[GBEMU_0xFF06];
        //TAC
        this.memoryWriter[GBEMU_0xFF07] = (parentObj, address, data) => {
            parentObj.memory[GBEMU_0xFF07] = data & GBEMU_0x07;
            parentObj.timaEnabled = (data & GBEMU_0x04) === GBEMU_0x04;
            parentObj.tacClocker = Math.pow(GBEMU_4, (data & GBEMU_0x3) !== 0 ? data & GBEMU_0x3 : GBEMU_4) << GBEMU_2; //TODO: Find a way to not make a conditional in here...
        };
        this.memoryHighWriter[GBEMU_0x7] = this.memoryWriter[GBEMU_0xFF07];
        //IF (Interrupt Request)
        this.memoryWriter[GBEMU_0xFF0F] = (parentObj, address, data) => {
            parentObj.interruptsRequested = data;
            parentObj.checkIRQMatching();
        };
        this.memoryHighWriter[GBEMU_0xF] = this.memoryWriter[GBEMU_0xFF0F];
        this.memoryWriter[GBEMU_0xFF10] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                if (parentObj.channel1decreaseSweep && (data & GBEMU_0x08) === 0) {
                    if (parentObj.channel1numSweep !== parentObj.channel1frequencySweepDivider) {
                        parentObj.channel1SweepFault = true;
                    }
                }
                parentObj.channel1lastTimeSweep = (data & GBEMU_0x70) >> GBEMU_4;
                parentObj.channel1frequencySweepDivider = data & GBEMU_0x07;
                parentObj.channel1decreaseSweep = (data & GBEMU_0x08) === GBEMU_0x08;
                parentObj.memory[GBEMU_0xFF10] = data;
                parentObj.channel1EnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x10] = this.memoryWriter[GBEMU_0xFF10];
        this.memoryWriter[GBEMU_0xFF11] = (parentObj, address, tempData) => {
            let data = tempData;
            if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
                if (parentObj.soundMasterEnabled) {
                    parentObj.audioJIT();
                }
                else {
                    data &= GBEMU_0x3F;
                }
                parentObj.channel1CachedDuty = parentObj.dutyLookup[data >> GBEMU_6];
                parentObj.channel1totalLength = GBEMU_0x40 - (data & GBEMU_0x3F);
                parentObj.memory[GBEMU_0xFF11] = data & GBEMU_0xC0;
                parentObj.channel1EnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x11] = this.memoryWriter[GBEMU_0xFF11];
        this.memoryWriter[GBEMU_0xFF12] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                if (parentObj.channel1Enabled && parentObj.channel1envelopeSweeps === 0) {
                    //Zombie Volume PAPU Bug:
                    if (((parentObj.memory[GBEMU_0xFF12] ^ data) & GBEMU_0x8) === GBEMU_0x8) {
                        if ((parentObj.memory[GBEMU_0xFF12] & GBEMU_0x8) === 0) {
                            (parentObj.memory[GBEMU_0xFF12] & GBEMU_0x7) === GBEMU_0x7 ?
                                (parentObj.channel1envelopeVolume += GBEMU_2) :
                                (parentObj.channel1envelopeVolume += 1);
                        }
                        parentObj.channel1envelopeVolume = (GBEMU_16 - parentObj.channel1envelopeVolume) & GBEMU_0xF;
                    }
                    else if ((parentObj.memory[GBEMU_0xFF12] & GBEMU_0xF) === GBEMU_0x8) {
                        parentObj.channel1envelopeVolume = (1 + parentObj.channel1envelopeVolume) & GBEMU_0xF;
                    }
                    parentObj.channel1OutputLevelCache();
                }
                parentObj.channel1envelopeType = (data & GBEMU_0x08) === GBEMU_0x08;
                parentObj.memory[GBEMU_0xFF12] = data;
                parentObj.channel1VolumeEnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x12] = this.memoryWriter[GBEMU_0xFF12];
        this.memoryWriter[GBEMU_0xFF13] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                parentObj.channel1frequency = (parentObj.channel1frequency & GBEMU_0x700) | data;
                parentObj.channel1FrequencyTracker = (GBEMU_0x800 - parentObj.channel1frequency) << GBEMU_2;
                parentObj.memory[GBEMU_0xFF13] = data;
            }
        };
        this.memoryHighWriter[GBEMU_0x13] = this.memoryWriter[GBEMU_0xFF13];
        this.memoryWriter[GBEMU_0xFF14] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                parentObj.channel1consecutive = (data & GBEMU_0x40) === GBEMU_0x0;
                parentObj.channel1frequency = ((data & GBEMU_0x7) << GBEMU_8) | (parentObj.channel1frequency & GBEMU_0xFF);
                parentObj.channel1FrequencyTracker = (GBEMU_0x800 - parentObj.channel1frequency) << GBEMU_2;
                if (data > GBEMU_0x7F) {
                    //Reload GBEMU_0xFF10:
                    parentObj.channel1timeSweep = parentObj.channel1lastTimeSweep;
                    parentObj.channel1numSweep = parentObj.channel1frequencySweepDivider;
                    //Reload GBEMU_0xFF12:
                    let nr12 = parentObj.memory[GBEMU_0xFF12];
                    parentObj.channel1envelopeVolume = nr12 >> GBEMU_4;
                    parentObj.channel1OutputLevelCache();
                    parentObj.channel1envelopeSweepsLast = (nr12 & GBEMU_0x7) - 1;
                    if (parentObj.channel1totalLength === 0) {
                        parentObj.channel1totalLength = GBEMU_0x40;
                    }
                    if (parentObj.channel1lastTimeSweep > 0 || parentObj.channel1frequencySweepDivider > 0) {
                        parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x1;
                    }
                    else {
                        parentObj.memory[GBEMU_0xFF26] &= GBEMU_0xFE;
                    }
                    if ((data & GBEMU_0x40) === GBEMU_0x40) {
                        parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x1;
                    }
                    parentObj.channel1ShadowFrequency = parentObj.channel1frequency;
                    //Reset frequency overflow check + frequency sweep type check:
                    parentObj.channel1SweepFault = false;
                    parentObj.runAudioSweep(); //Supposed to run immediately
                }
                parentObj.channel1EnableCheck();
                parentObj.memory[GBEMU_0xFF14] = data & GBEMU_0x40;
            }
        };
        this.memoryHighWriter[GBEMU_0x14] = this.memoryWriter[GBEMU_0xFF14];
        this.memoryWriter[GBEMU_0xFF16] = (parentObj, address, tempData) => {
            let data = tempData;
            if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
                if (parentObj.soundMasterEnabled) {
                    parentObj.audioJIT();
                }
                else {
                    data &= GBEMU_0x3F;
                }
                parentObj.channel2CachedDuty = parentObj.dutyLookup[data >> GBEMU_6];
                parentObj.channel2totalLength = GBEMU_0x40 - (data & GBEMU_0x3F);
                parentObj.memory[GBEMU_0xFF16] = data & GBEMU_0xC0;
                parentObj.channel2EnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x16] = this.memoryWriter[GBEMU_0xFF16];
        this.memoryWriter[GBEMU_0xFF17] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                if (parentObj.channel2Enabled && parentObj.channel2envelopeSweeps === 0) {
                    //Zombie Volume PAPU Bug:
                    if (((parentObj.memory[GBEMU_0xFF17] ^ data) & GBEMU_0x8) === GBEMU_0x8) {
                        if ((parentObj.memory[GBEMU_0xFF17] & GBEMU_0x8) === 0) {
                            (parentObj.memory[GBEMU_0xFF17] & GBEMU_0x7) === GBEMU_0x7 ?
                                (parentObj.channel2envelopeVolume += GBEMU_2) :
                                (parentObj.channel2envelopeVolume += 1);
                        }
                        parentObj.channel2envelopeVolume = (GBEMU_16 - parentObj.channel2envelopeVolume) & GBEMU_0xF;
                    }
                    else if ((parentObj.memory[GBEMU_0xFF17] & GBEMU_0xF) === GBEMU_0x8) {
                        parentObj.channel2envelopeVolume = (1 + parentObj.channel2envelopeVolume) & GBEMU_0xF;
                    }
                    parentObj.channel2OutputLevelCache();
                }
                parentObj.channel2envelopeType = (data & GBEMU_0x08) === GBEMU_0x08;
                parentObj.memory[GBEMU_0xFF17] = data;
                parentObj.channel2VolumeEnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x17] = this.memoryWriter[GBEMU_0xFF17];
        this.memoryWriter[GBEMU_0xFF18] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                parentObj.channel2frequency = (parentObj.channel2frequency & GBEMU_0x700) | data;
                parentObj.channel2FrequencyTracker = (GBEMU_0x800 - parentObj.channel2frequency) << GBEMU_2;
                parentObj.memory[GBEMU_0xFF18] = data;
            }
        };
        this.memoryHighWriter[GBEMU_0x18] = this.memoryWriter[GBEMU_0xFF18];
        this.memoryWriter[GBEMU_0xFF19] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                if (data > GBEMU_0x7F) {
                    //Reload GBEMU_0xFF17:
                    let nr22 = parentObj.memory[GBEMU_0xFF17];
                    parentObj.channel2envelopeVolume = nr22 >> GBEMU_4;
                    parentObj.channel2OutputLevelCache();
                    parentObj.channel2envelopeSweepsLast = (nr22 & GBEMU_0x7) - 1;
                    if (parentObj.channel2totalLength === 0) {
                        parentObj.channel2totalLength = GBEMU_0x40;
                    }
                    if ((data & GBEMU_0x40) === GBEMU_0x40) {
                        parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x2;
                    }
                }
                parentObj.channel2consecutive = (data & GBEMU_0x40) === GBEMU_0x0;
                parentObj.channel2frequency = ((data & GBEMU_0x7) << GBEMU_8) | (parentObj.channel2frequency & GBEMU_0xFF);
                parentObj.channel2FrequencyTracker = (GBEMU_0x800 - parentObj.channel2frequency) << GBEMU_2;
                parentObj.memory[GBEMU_0xFF19] = data & GBEMU_0x40;
                parentObj.channel2EnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x19] = this.memoryWriter[GBEMU_0xFF19];
        this.memoryWriter[GBEMU_0xFF1A] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                if (!parentObj.channel3canPlay && data >= GBEMU_0x80) {
                    parentObj.channel3lastSampleLookup = 0;
                    parentObj.channel3UpdateCache();
                }
                parentObj.channel3canPlay = data > GBEMU_0x7F;
                if (parentObj.channel3canPlay && parentObj.memory[GBEMU_0xFF1A] > GBEMU_0x7F && !parentObj.channel3consecutive) {
                    parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x4;
                }
                parentObj.memory[GBEMU_0xFF1A] = data & GBEMU_0x80;
                //parentObj.channel3EnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x1A] = this.memoryWriter[GBEMU_0xFF1A];
        this.memoryWriter[GBEMU_0xFF1B] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
                if (parentObj.soundMasterEnabled) {
                    parentObj.audioJIT();
                }
                parentObj.channel3totalLength = GBEMU_0x100 - data;
                parentObj.memory[GBEMU_0xFF1B] = data;
                parentObj.channel3EnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x1B] = this.memoryWriter[GBEMU_0xFF1B];
        this.memoryWriter[GBEMU_0xFF1C] = (parentObj, address, tempData) => {
            let data = tempData;
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                data &= GBEMU_0x60;
                parentObj.memory[GBEMU_0xFF1C] = data;
                parentObj.channel3patternType = data === 0 ? GBEMU_4 : (data >> GBEMU_5) - 1;
            }
        };
        this.memoryHighWriter[GBEMU_0x1C] = this.memoryWriter[GBEMU_0xFF1C];
        this.memoryWriter[GBEMU_0xFF1D] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                parentObj.channel3frequency = (parentObj.channel3frequency & GBEMU_0x700) | data;
                parentObj.channel3FrequencyPeriod = (GBEMU_0x800 - parentObj.channel3frequency) << 1;
                parentObj.memory[GBEMU_0xFF1D] = data;
            }
        };
        this.memoryHighWriter[GBEMU_0x1D] = this.memoryWriter[GBEMU_0xFF1D];
        this.memoryWriter[GBEMU_0xFF1E] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                if (data > GBEMU_0x7F) {
                    if (parentObj.channel3totalLength === 0) {
                        parentObj.channel3totalLength = GBEMU_0x100;
                    }
                    parentObj.channel3lastSampleLookup = 0;
                    if ((data & GBEMU_0x40) === GBEMU_0x40) {
                        parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x4;
                    }
                }
                parentObj.channel3consecutive = (data & GBEMU_0x40) === GBEMU_0x0;
                parentObj.channel3frequency = ((data & GBEMU_0x7) << GBEMU_8) | (parentObj.channel3frequency & GBEMU_0xFF);
                parentObj.channel3FrequencyPeriod = (GBEMU_0x800 - parentObj.channel3frequency) << 1;
                parentObj.memory[GBEMU_0xFF1E] = data & GBEMU_0x40;
                parentObj.channel3EnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x1E] = this.memoryWriter[GBEMU_0xFF1E];
        this.memoryWriter[GBEMU_0xFF20] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled || !parentObj.cGBC) {
                if (parentObj.soundMasterEnabled) {
                    parentObj.audioJIT();
                }
                parentObj.channel4totalLength = GBEMU_0x40 - (data & GBEMU_0x3F);
                parentObj.memory[GBEMU_0xFF20] = data | GBEMU_0xC0;
                parentObj.channel4EnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x20] = this.memoryWriter[GBEMU_0xFF20];
        this.memoryWriter[GBEMU_0xFF21] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                if (parentObj.channel4Enabled && parentObj.channel4envelopeSweeps === 0) {
                    //Zombie Volume PAPU Bug:
                    if (((parentObj.memory[GBEMU_0xFF21] ^ data) & GBEMU_0x8) === GBEMU_0x8) {
                        if ((parentObj.memory[GBEMU_0xFF21] & GBEMU_0x8) === 0) {
                            (parentObj.memory[GBEMU_0xFF21] & GBEMU_0x7) === GBEMU_0x7 ?
                                (parentObj.channel4envelopeVolume += GBEMU_2) :
                                (parentObj.channel4envelopeVolume += 1);
                        }
                        parentObj.channel4envelopeVolume = (GBEMU_16 - parentObj.channel4envelopeVolume) & GBEMU_0xF;
                    }
                    else if ((parentObj.memory[GBEMU_0xFF21] & GBEMU_0xF) === GBEMU_0x8) {
                        parentObj.channel4envelopeVolume = (1 + parentObj.channel4envelopeVolume) & GBEMU_0xF;
                    }
                    parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << parentObj.channel4VolumeShifter;
                }
                parentObj.channel4envelopeType = (data & GBEMU_0x08) === GBEMU_0x08;
                parentObj.memory[GBEMU_0xFF21] = data;
                parentObj.channel4UpdateCache();
                parentObj.channel4VolumeEnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x21] = this.memoryWriter[GBEMU_0xFF21];
        this.memoryWriter[GBEMU_0xFF22] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                parentObj.channel4FrequencyPeriod = Math.max((data & GBEMU_0x7) << GBEMU_4, GBEMU_8) << (data >> GBEMU_4);
                let bitWidth = data & GBEMU_0x8;
                if ((bitWidth === GBEMU_0x8 && parentObj.channel4BitRange === GBEMU_0x7FFF) || (bitWidth === 0 && parentObj.channel4BitRange === GBEMU_0x7F)) {
                    parentObj.channel4lastSampleLookup = 0;
                    parentObj.channel4BitRange = bitWidth === GBEMU_0x8 ? GBEMU_0x7F : GBEMU_0x7FFF;
                    parentObj.channel4VolumeShifter = bitWidth === GBEMU_0x8 ? GBEMU_7 : GBEMU_15;
                    parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << parentObj.channel4VolumeShifter;
                    parentObj.noiseSampleTable = bitWidth === GBEMU_0x8 ? parentObj.lsfr7Table : parentObj.lsfr15Table;
                }
                parentObj.memory[GBEMU_0xFF22] = data;
                parentObj.channel4UpdateCache();
            }
        };
        this.memoryHighWriter[GBEMU_0x22] = this.memoryWriter[GBEMU_0xFF22];
        this.memoryWriter[GBEMU_0xFF23] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled) {
                parentObj.audioJIT();
                parentObj.memory[GBEMU_0xFF23] = data;
                parentObj.channel4consecutive = (data & GBEMU_0x40) === GBEMU_0x0;
                if (data > GBEMU_0x7F) {
                    let nr42 = parentObj.memory[GBEMU_0xFF21];
                    parentObj.channel4envelopeVolume = nr42 >> GBEMU_4;
                    parentObj.channel4currentVolume = parentObj.channel4envelopeVolume << parentObj.channel4VolumeShifter;
                    parentObj.channel4envelopeSweepsLast = (nr42 & GBEMU_0x7) - 1;
                    if (parentObj.channel4totalLength === 0) {
                        parentObj.channel4totalLength = GBEMU_0x40;
                    }
                    if ((data & GBEMU_0x40) === GBEMU_0x40) {
                        parentObj.memory[GBEMU_0xFF26] |= GBEMU_0x8;
                    }
                }
                parentObj.channel4EnableCheck();
            }
        };
        this.memoryHighWriter[GBEMU_0x23] = this.memoryWriter[GBEMU_0xFF23];
        this.memoryWriter[GBEMU_0xFF24] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled && parentObj.memory[GBEMU_0xFF24] !== data) {
                parentObj.audioJIT();
                parentObj.memory[GBEMU_0xFF24] = data;
                parentObj.vinLeftChannelMasterVolume = ((data >> GBEMU_4) & GBEMU_0x07) + 1;
                parentObj.vinRightChannelMasterVolume = (data & GBEMU_0x07) + 1;
                parentObj.mixerOutputLevelCache();
            }
        };
        this.memoryHighWriter[GBEMU_0x24] = this.memoryWriter[GBEMU_0xFF24];
        this.memoryWriter[GBEMU_0xFF25] = (parentObj, address, data) => {
            if (parentObj.soundMasterEnabled && parentObj.memory[GBEMU_0xFF25] !== data) {
                parentObj.audioJIT();
                parentObj.memory[GBEMU_0xFF25] = data;
                parentObj.rightChannel1 = (data & GBEMU_0x01) === GBEMU_0x01;
                parentObj.rightChannel2 = (data & GBEMU_0x02) === GBEMU_0x02;
                parentObj.rightChannel3 = (data & GBEMU_0x04) === GBEMU_0x04;
                parentObj.rightChannel4 = (data & GBEMU_0x08) === GBEMU_0x08;
                parentObj.leftChannel1 = (data & GBEMU_0x10) === GBEMU_0x10;
                parentObj.leftChannel2 = (data & GBEMU_0x20) === GBEMU_0x20;
                parentObj.leftChannel3 = (data & GBEMU_0x40) === GBEMU_0x40;
                parentObj.leftChannel4 = data > GBEMU_0x7F;
                parentObj.channel1OutputLevelCache();
                parentObj.channel2OutputLevelCache();
                parentObj.channel3OutputLevelCache();
                parentObj.channel4OutputLevelCache();
            }
        };
        this.memoryHighWriter[GBEMU_0x25] = this.memoryWriter[GBEMU_0xFF25];
        this.memoryWriter[GBEMU_0xFF26] = (parentObj, address, data) => {
            parentObj.audioJIT();
            if (!parentObj.soundMasterEnabled && data > GBEMU_0x7F) {
                parentObj.memory[GBEMU_0xFF26] = GBEMU_0x80;
                parentObj.soundMasterEnabled = true;
                parentObj.initializeAudioStartState();
            }
            else if (parentObj.soundMasterEnabled && data < GBEMU_0x80) {
                parentObj.memory[GBEMU_0xFF26] = 0;
                parentObj.soundMasterEnabled = false;
                //GBDev wiki says the registers are written with zeros on power off:
                for (let index = GBEMU_0xFF10; index < GBEMU_0xFF26; index++) {
                    parentObj.memoryWriter[index](parentObj, index, 0);
                }
            }
        };
        this.memoryHighWriter[GBEMU_0x26] = this.memoryWriter[GBEMU_0xFF26];
        //GBEMU_0xFF27 to GBEMU_0xFF2F don't do anything...
        this.memoryHighWriter[GBEMU_0x27] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF27] = this.cartIgnoreWrite;
        this.memoryHighWriter[GBEMU_0x28] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF28] = this.cartIgnoreWrite;
        this.memoryHighWriter[GBEMU_0x29] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF29] = this.cartIgnoreWrite;
        this.memoryHighWriter[GBEMU_0x2A] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF2A] = this.cartIgnoreWrite;
        this.memoryHighWriter[GBEMU_0x2B] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF2B] = this.cartIgnoreWrite;
        this.memoryHighWriter[GBEMU_0x2C] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF2C] = this.cartIgnoreWrite;
        this.memoryHighWriter[GBEMU_0x2D] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF2D] = this.cartIgnoreWrite;
        this.memoryHighWriter[GBEMU_0x2E] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF2E] = this.cartIgnoreWrite;
        this.memoryHighWriter[GBEMU_0x2F] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF2F] = this.cartIgnoreWrite;
        //WAVE PCM RAM:
        this.memoryWriter[GBEMU_0xFF30] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(0, data);
        };
        this.memoryHighWriter[GBEMU_0x30] = this.memoryWriter[GBEMU_0xFF30];
        this.memoryWriter[GBEMU_0xFF31] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0x1, data);
        };
        this.memoryHighWriter[GBEMU_0x31] = this.memoryWriter[GBEMU_0xFF31];
        this.memoryWriter[GBEMU_0xFF32] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0x2, data);
        };
        this.memoryHighWriter[GBEMU_0x32] = this.memoryWriter[GBEMU_0xFF32];
        this.memoryWriter[GBEMU_0xFF33] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0x3, data);
        };
        this.memoryHighWriter[GBEMU_0x33] = this.memoryWriter[GBEMU_0xFF33];
        this.memoryWriter[GBEMU_0xFF34] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0x4, data);
        };
        this.memoryHighWriter[GBEMU_0x34] = this.memoryWriter[GBEMU_0xFF34];
        this.memoryWriter[GBEMU_0xFF35] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0x5, data);
        };
        this.memoryHighWriter[GBEMU_0x35] = this.memoryWriter[GBEMU_0xFF35];
        this.memoryWriter[GBEMU_0xFF36] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0x6, data);
        };
        this.memoryHighWriter[GBEMU_0x36] = this.memoryWriter[GBEMU_0xFF36];
        this.memoryWriter[GBEMU_0xFF37] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0x7, data);
        };
        this.memoryHighWriter[GBEMU_0x37] = this.memoryWriter[GBEMU_0xFF37];
        this.memoryWriter[GBEMU_0xFF38] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0x8, data);
        };
        this.memoryHighWriter[GBEMU_0x38] = this.memoryWriter[GBEMU_0xFF38];
        this.memoryWriter[GBEMU_0xFF39] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0x9, data);
        };
        this.memoryHighWriter[GBEMU_0x39] = this.memoryWriter[GBEMU_0xFF39];
        this.memoryWriter[GBEMU_0xFF3A] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0xA, data);
        };
        this.memoryHighWriter[GBEMU_0x3A] = this.memoryWriter[GBEMU_0xFF3A];
        this.memoryWriter[GBEMU_0xFF3B] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0xB, data);
        };
        this.memoryHighWriter[GBEMU_0x3B] = this.memoryWriter[GBEMU_0xFF3B];
        this.memoryWriter[GBEMU_0xFF3C] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0xC, data);
        };
        this.memoryHighWriter[GBEMU_0x3C] = this.memoryWriter[GBEMU_0xFF3C];
        this.memoryWriter[GBEMU_0xFF3D] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0xD, data);
        };
        this.memoryHighWriter[GBEMU_0x3D] = this.memoryWriter[GBEMU_0xFF3D];
        this.memoryWriter[GBEMU_0xFF3E] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0xE, data);
        };
        this.memoryHighWriter[GBEMU_0x3E] = this.memoryWriter[GBEMU_0xFF3E];
        this.memoryWriter[GBEMU_0xFF3F] = (parentObj, address, data) => {
            parentObj.channel3WriteRAM(GBEMU_0xF, data);
        };
        this.memoryHighWriter[GBEMU_0x3F] = this.memoryWriter[GBEMU_0xFF3F];
        //SCY
        this.memoryWriter[GBEMU_0xFF42] = (parentObj, address, data) => {
            if (parentObj.backgroundY !== data) {
                parentObj.midScanLineJIT();
                parentObj.backgroundY = data;
            }
        };
        this.memoryHighWriter[GBEMU_0x42] = this.memoryWriter[GBEMU_0xFF42];
        //SCX
        this.memoryWriter[GBEMU_0xFF43] = (parentObj, address, data) => {
            if (parentObj.backgroundX !== data) {
                parentObj.midScanLineJIT();
                parentObj.backgroundX = data;
            }
        };
        this.memoryHighWriter[GBEMU_0x43] = this.memoryWriter[GBEMU_0xFF43];
        //LY
        this.memoryWriter[GBEMU_0xFF44] = (parentObj, address, data) => {
            //Read Only:
            if (parentObj.lcdIsOn) {
                //Gambatte says to do this:
                parentObj.modeSTAT = GBEMU_2;
                parentObj.midScanlineOffset = -1;
                parentObj.totalLinesPassed = 0;
                parentObj.currentX = 0;
                parentObj.queuedScanLines = 0;
                parentObj.lastUnrenderedLine = 0;
                parentObj.lcdTicks = 0;
                parentObj.statTracker = 0;
                parentObj.actualScanLine = 0;
                parentObj.memory[GBEMU_0xFF44] = 0;
            }
        };
        this.memoryHighWriter[GBEMU_0x44] = this.memoryWriter[GBEMU_0xFF44];
        //LYC
        this.memoryWriter[GBEMU_0xFF45] = (parentObj, address, data) => {
            if (parentObj.memory[GBEMU_0xFF45] !== data) {
                parentObj.memory[GBEMU_0xFF45] = data;
                if (parentObj.lcdIsOn) {
                    parentObj.matchLYC(); //Get the compare of the first scan line.
                }
            }
        };
        this.memoryHighWriter[GBEMU_0x45] = this.memoryWriter[GBEMU_0xFF45];
        //WY
        this.memoryWriter[GBEMU_0xFF4A] = (parentObj, address, data) => {
            if (parentObj.windowY !== data) {
                parentObj.midScanLineJIT();
                parentObj.windowY = data;
            }
        };
        this.memoryHighWriter[GBEMU_0x4A] = this.memoryWriter[GBEMU_0xFF4A];
        //WX
        this.memoryWriter[GBEMU_0xFF4B] = (parentObj, address, data) => {
            if (parentObj.memory[GBEMU_0xFF4B] !== data) {
                parentObj.midScanLineJIT();
                parentObj.memory[GBEMU_0xFF4B] = data;
                parentObj.windowX = data - GBEMU_7;
            }
        };
        this.memoryHighWriter[GBEMU_0x4B] = this.memoryWriter[GBEMU_0xFF4B];
        this.memoryWriter[GBEMU_0xFF72] = (parentObj, address, data) => {
            parentObj.memory[GBEMU_0xFF72] = data;
        };
        this.memoryHighWriter[GBEMU_0x72] = this.memoryWriter[GBEMU_0xFF72];
        this.memoryWriter[GBEMU_0xFF73] = (parentObj, address, data) => {
            parentObj.memory[GBEMU_0xFF73] = data;
        };
        this.memoryHighWriter[GBEMU_0x73] = this.memoryWriter[GBEMU_0xFF73];
        this.memoryWriter[GBEMU_0xFF75] = (parentObj, address, data) => {
            parentObj.memory[GBEMU_0xFF75] = data;
        };
        this.memoryHighWriter[GBEMU_0x75] = this.memoryWriter[GBEMU_0xFF75];
        this.memoryHighWriter[GBEMU_0x76] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF76] = this.cartIgnoreWrite;
        this.memoryHighWriter[GBEMU_0x77] = this.cartIgnoreWrite;
        this.memoryWriter[GBEMU_0xFF77] = this.cartIgnoreWrite;
        //IE (Interrupt Enable)
        this.memoryWriter[GBEMU_0xFFFF] = (parentObj, address, data) => {
            parentObj.interruptsEnabled = data;
            parentObj.checkIRQMatching();
        };
        this.memoryHighWriter[GBEMU_0xFF] = this.memoryWriter[GBEMU_0xFFFF];
        this.recompileModelSpecificIOWriteHandling();
        this.recompileBootIOWriteHandling();
    }
    recompileModelSpecificIOWriteHandling() {
        //debugLog('This is recompileModelSpecificIOWriteHandling');
        if (this.cGBC) {
            //GameBoy Color Specific I/O:
            //SC (Serial Transfer Control Register)
            this.memoryWriter[GBEMU_0xFF02] = (parentObj, address, data) => {
                if ((data & GBEMU_0x1) === GBEMU_0x1) {
                    //Internal clock:
                    parentObj.memory[GBEMU_0xFF02] = data & GBEMU_0x7F;
                    parentObj.serialTimer = (data & GBEMU_0x2) === 0 ? GBEMU_4096 : GBEMU_128; //Set the Serial IRQ counter.
                    parentObj.serialShiftTimer = (data & GBEMU_0x2) === 0 ? GBEMU_512 : GBEMU_16; //Set the transfer data shift counter.
                    parentObj.serialShiftTimerAllocated = parentObj.serialShiftTimer;
                }
                else {
                    //External clock:
                    parentObj.memory[GBEMU_0xFF02] = data;
                    parentObj.serialShiftTimer = 0; //Zero the timers, since we're emulating as if nothing is connected.
                    parentObj.serialShiftTimerAllocated = parentObj.serialShiftTimer;
                    parentObj.serialTimer = parentObj.serialShiftTimer;
                }
            };
            this.memoryHighWriter[GBEMU_0x2] = this.memoryWriter[GBEMU_0xFF02];
            this.memoryWriter[GBEMU_0xFF40] = (parentObj, address, data) => {
                if (parentObj.memory[GBEMU_0xFF40] !== data) {
                    parentObj.midScanLineJIT();
                    let tempVar = data > GBEMU_0x7F;
                    if (tempVar !== parentObj.lcdIsOn) {
                        //When the display mode changes...
                        parentObj.lcdIsOn = tempVar;
                        parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x78;
                        parentObj.midScanlineOffset = -1;
                        parentObj.totalLinesPassed = 0;
                        parentObj.currentX = 0;
                        parentObj.queuedScanLines = 0;
                        parentObj.lastUnrenderedLine = 0;
                        parentObj.statTracker = 0;
                        parentObj.lcdTicks = 0;
                        parentObj.actualScanLine = 0;
                        parentObj.memory[GBEMU_0xFF44] = 0;
                        if (parentObj.lcdIsOn) {
                            parentObj.modeSTAT = GBEMU_2;
                            parentObj.matchLYC(); //Get the compare of the first scan line.
                            parentObj.lcdControl = parentObj.lineControl;
                        }
                        else {
                            parentObj.modeSTAT = 0;
                            parentObj.lcdControl = parentObj.disPlayOffControl;
                            parentObj.displayShowOff();
                        }
                        parentObj.interruptsRequested &= GBEMU_0xFD;
                    }
                    parentObj.gfxWindowCHRBankPosition = (data & GBEMU_0x40) === GBEMU_0x40 ? GBEMU_0x400 : 0;
                    parentObj.gfxWindowDisplay = (data & GBEMU_0x20) === GBEMU_0x20;
                    parentObj.gfxBackgroundBankOffset = (data & GBEMU_0x10) === GBEMU_0x10 ? 0 : GBEMU_0x80;
                    parentObj.gfxBackgroundCHRBankPosition = (data & GBEMU_0x08) === GBEMU_0x08 ? GBEMU_0x400 : 0;
                    parentObj.gfxSpriteNormalHeight = (data & GBEMU_0x04) === 0;
                    parentObj.gfxSpriteShow = (data & GBEMU_0x02) === GBEMU_0x02;
                    parentObj.bgPriorityEnabled = (data & GBEMU_0x01) === GBEMU_0x01;
                    parentObj.priorityFlaggingPathRebuild(); //Special case the priority flagging as an optimization.
                    parentObj.memory[GBEMU_0xFF40] = data;
                }
            };
            this.memoryHighWriter[GBEMU_0x40] = this.memoryWriter[GBEMU_0xFF40];
            this.memoryWriter[GBEMU_0xFF41] = (parentObj, address, data) => {
                parentObj.lycMatchTriggerSTAT = (data & GBEMU_0x40) === GBEMU_0x40;
                parentObj.mode2TriggerSTAT = (data & GBEMU_0x20) === GBEMU_0x20;
                parentObj.mode1TriggerSTAT = (data & GBEMU_0x10) === GBEMU_0x10;
                parentObj.mode0TriggerSTAT = (data & GBEMU_0x08) === GBEMU_0x08;
                parentObj.memory[GBEMU_0xFF41] = data & GBEMU_0x78;
            };
            this.memoryHighWriter[GBEMU_0x41] = this.memoryWriter[GBEMU_0xFF41];
            this.memoryWriter[GBEMU_0xFF46] = (parentObj, addressTemp, dataTemp) => {
                let data = dataTemp;
                let address = addressTemp;
                parentObj.memory[GBEMU_0xFF46] = data;
                if (data < GBEMU_0xE0) {
                    data <<= GBEMU_8;
                    address = GBEMU_0xFE00;
                    let stat = parentObj.modeSTAT;
                    parentObj.modeSTAT = GBEMU_0;
                    let newData = GBEMU_0;
                    do {
                        newData = parentObj.memoryReader[data](parentObj, data++);
                        if (newData !== parentObj.memory[address]) {
                            parentObj.modeSTAT = stat; //JIT the graphics render queue
                            parentObj.graphicsJIT();
                            parentObj.modeSTAT = GBEMU_0;
                            parentObj.memory[address++] = newData;
                            break;
                        }
                        address += 1;
                    } while (address < GBEMU_0xFEA0);
                    if (address < GBEMU_0xFEA0) {
                        do {
                            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
                            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
                            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
                            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
                        } while (address < GBEMU_0xFEA0);
                    }
                    parentObj.modeSTAT = stat;
                }
            };
            this.memoryHighWriter[GBEMU_0x46] = this.memoryWriter[GBEMU_0xFF46];
            //KEY1
            this.memoryWriter[GBEMU_0xFF4D] = (parentObj, address, data) => {
                let temp = parentObj.memory[GBEMU_0xFF4D] & GBEMU_0x80;
                parentObj.memory[GBEMU_0xFF4D] = (data & GBEMU_0x7F) | temp;
            };
            this.memoryHighWriter[GBEMU_0x4D] = this.memoryWriter[GBEMU_0xFF4D];
            this.memoryWriter[GBEMU_0xFF4F] = (parentObj, address, data) => {
                parentObj.currvramBank = data & GBEMU_0x01;
                if (parentObj.currvramBank > 0) {
                    parentObj.bgCHRCurrentBank = parentObj.bgCHRBank2;
                }
                else {
                    parentObj.bgCHRCurrentBank = parentObj.bgCHRBank1;
                }
                //Only writable by GBC.
            };
            this.memoryHighWriter[GBEMU_0x4F] = this.memoryWriter[GBEMU_0xFF4F];
            this.memoryWriter[GBEMU_0xFF51] = (parentObj, address, data) => {
                if (!parentObj.hdmaRunning) {
                    parentObj.memory[GBEMU_0xFF51] = data;
                }
            };
            this.memoryHighWriter[GBEMU_0x51] = this.memoryWriter[GBEMU_0xFF51];
            this.memoryWriter[GBEMU_0xFF52] = (parentObj, address, data) => {
                if (!parentObj.hdmaRunning) {
                    parentObj.memory[GBEMU_0xFF52] = data & GBEMU_0xF0;
                }
            };
            this.memoryHighWriter[GBEMU_0x52] = this.memoryWriter[GBEMU_0xFF52];
            this.memoryWriter[GBEMU_0xFF53] = (parentObj, address, data) => {
                if (!parentObj.hdmaRunning) {
                    parentObj.memory[GBEMU_0xFF53] = data & GBEMU_0x1F;
                }
            };
            this.memoryHighWriter[GBEMU_0x53] = this.memoryWriter[GBEMU_0xFF53];
            this.memoryWriter[GBEMU_0xFF54] = (parentObj, address, data) => {
                if (!parentObj.hdmaRunning) {
                    parentObj.memory[GBEMU_0xFF54] = data & GBEMU_0xF0;
                }
            };
            this.memoryHighWriter[GBEMU_0x54] = this.memoryWriter[GBEMU_0xFF54];
            this.memoryWriter[GBEMU_0xFF55] = (parentObj, address, data) => {
                if (!parentObj.hdmaRunning) {
                    if ((data & GBEMU_0x80) === 0) {
                        //DMA
                        parentObj.dMAWrite((data & GBEMU_0x7F) + 1);
                        parentObj.memory[GBEMU_0xFF55] = GBEMU_0xFF; //Transfer completed.
                    }
                    else {
                        //H-Blank DMA
                        parentObj.hdmaRunning = true;
                        parentObj.memory[GBEMU_0xFF55] = data & GBEMU_0x7F;
                    }
                }
                else if ((data & GBEMU_0x80) === 0) {
                    //Stop H-Blank DMA
                    parentObj.hdmaRunning = false;
                    parentObj.memory[GBEMU_0xFF55] |= GBEMU_0x80;
                }
                else {
                    parentObj.memory[GBEMU_0xFF55] = data & GBEMU_0x7F;
                }
            };
            this.memoryHighWriter[GBEMU_0x55] = this.memoryWriter[GBEMU_0xFF55];
            this.memoryWriter[GBEMU_0xFF68] = (parentObj, address, data) => {
                parentObj.memory[GBEMU_0xFF69] = parentObj.gbcBGRawPalette[data & GBEMU_0x3F];
                parentObj.memory[GBEMU_0xFF68] = data;
            };
            this.memoryHighWriter[GBEMU_0x68] = this.memoryWriter[GBEMU_0xFF68];
            this.memoryWriter[GBEMU_0xFF69] = (parentObj, address, data) => {
                parentObj.updateGBCBGPalette(parentObj.memory[GBEMU_0xFF68] & GBEMU_0x3F, data);
                if (parentObj.memory[GBEMU_0xFF68] > GBEMU_0x7F) {
                    // high bit = autoincrement
                    let next = (parentObj.memory[GBEMU_0xFF68] + 1) & GBEMU_0x3F;
                    parentObj.memory[GBEMU_0xFF68] = next | GBEMU_0x80;
                    parentObj.memory[GBEMU_0xFF69] = parentObj.gbcBGRawPalette[next];
                }
                else {
                    parentObj.memory[GBEMU_0xFF69] = data;
                }
            };
            this.memoryHighWriter[GBEMU_0x69] = this.memoryWriter[GBEMU_0xFF69];
            this.memoryWriter[GBEMU_0xFF6A] = (parentObj, address, data) => {
                parentObj.memory[GBEMU_0xFF6B] = parentObj.gbcOBJRawPalette[data & GBEMU_0x3F];
                parentObj.memory[GBEMU_0xFF6A] = data;
            };
            this.memoryHighWriter[GBEMU_0x6A] = this.memoryWriter[GBEMU_0xFF6A];
            this.memoryWriter[GBEMU_0xFF6B] = (parentObj, address, data) => {
                let temp = parentObj.memory[GBEMU_0xFF6A];
                parentObj.updateGBCOBJPalette(temp & GBEMU_0x3F, data);
                if (temp > GBEMU_0x7F) {
                    // high bit = autoincrement
                    let next = (parentObj.memory[GBEMU_0xFF6A] + 1) & GBEMU_0x3F;
                    parentObj.memory[GBEMU_0xFF6A] = next | GBEMU_0x80;
                    parentObj.memory[GBEMU_0xFF6B] = parentObj.gbcOBJRawPalette[next];
                }
                else {
                    parentObj.memory[GBEMU_0xFF6B] = data;
                }
            };
            this.memoryHighWriter[GBEMU_0x6B] = this.memoryWriter[GBEMU_0xFF6B];
            //SVBK
            this.memoryWriter[GBEMU_0xFF70] = (parentObj, address, data) => {
                let addressCheck = (parentObj.memory[GBEMU_0xFF51] << GBEMU_8) | parentObj.memory[GBEMU_0xFF52]; //Cannot change the RAM bank while WRAM is the source of a running HDMA.
                if (!parentObj.hdmaRunning || addressCheck < GBEMU_0xD000 || addressCheck >= GBEMU_0xE000) {
                    parentObj.gbcRamBank = Math.max(data & GBEMU_0x07, 1); //Bank range is from 1-GBEMU_7
                    parentObj.gbcRamBankPosition = ((parentObj.gbcRamBank - 1) << GBEMU_12) - GBEMU_0xD000;
                    parentObj.gbcRamBankPositionECHO = parentObj.gbcRamBankPosition - GBEMU_0x2000;
                }
                parentObj.memory[GBEMU_0xFF70] = data; //Bit GBEMU_6 cannot be written to.
            };
            this.memoryHighWriter[GBEMU_0x70] = this.memoryWriter[GBEMU_0xFF70];
            this.memoryWriter[GBEMU_0xFF74] = (parentObj, address, data) => {
                parentObj.memory[GBEMU_0xFF74] = data;
            };
            this.memoryHighWriter[GBEMU_0x74] = this.memoryWriter[GBEMU_0xFF74];
        }
        else {
            //Fill in the GameBoy Color I/O registers as normal RAM for GameBoy compatibility:
            //SC (Serial Transfer Control Register)
            this.memoryWriter[GBEMU_0xFF02] = (parentObj, address, data) => {
                if ((data & GBEMU_0x1) === GBEMU_0x1) {
                    //Internal clock:
                    parentObj.memory[GBEMU_0xFF02] = data & GBEMU_0x7F;
                    parentObj.serialTimer = GBEMU_4096; //Set the Serial IRQ counter.
                    parentObj.serialShiftTimer = GBEMU_512;
                    parentObj.serialShiftTimerAllocated = GBEMU_512; //Set the transfer data shift counter.
                }
                else {
                    //External clock:
                    parentObj.memory[GBEMU_0xFF02] = data;
                    parentObj.serialShiftTimer = 0;
                    parentObj.serialShiftTimerAllocated = 0;
                    parentObj.serialTimer = 0; //Zero the timers, since we're emulating as if nothing is connected.
                }
            };
            this.memoryHighWriter[GBEMU_0x2] = this.memoryWriter[GBEMU_0xFF02];
            this.memoryWriter[GBEMU_0xFF40] = (parentObj, address, data) => {
                if (parentObj.memory[GBEMU_0xFF40] !== data) {
                    parentObj.midScanLineJIT();
                    let tempVar = data > GBEMU_0x7F;
                    if (tempVar !== parentObj.lcdIsOn) {
                        //When the display mode changes...
                        parentObj.lcdIsOn = tempVar;
                        parentObj.memory[GBEMU_0xFF41] &= GBEMU_0x78;
                        parentObj.midScanlineOffset = -1;
                        parentObj.totalLinesPassed = 0;
                        parentObj.currentX = 0;
                        parentObj.queuedScanLines = 0;
                        parentObj.lastUnrenderedLine = 0;
                        parentObj.statTracker = 0;
                        parentObj.lcdTicks = 0;
                        parentObj.actualScanLine = 0;
                        parentObj.memory[GBEMU_0xFF44] = 0;
                        if (parentObj.lcdIsOn) {
                            parentObj.modeSTAT = GBEMU_2;
                            parentObj.matchLYC(); //Get the compare of the first scan line.
                            parentObj.lcdControl = parentObj.lineControl;
                        }
                        else {
                            parentObj.modeSTAT = 0;
                            parentObj.lcdControl = parentObj.disPlayOffControl;
                            parentObj.displayShowOff();
                        }
                        parentObj.interruptsRequested &= 0xfd;
                    }
                    parentObj.gfxWindowCHRBankPosition = (data & GBEMU_0x40) === GBEMU_0x40 ? GBEMU_0x400 : 0;
                    parentObj.gfxWindowDisplay = (data & GBEMU_0x20) === GBEMU_0x20;
                    parentObj.gfxBackgroundBankOffset = (data & GBEMU_0x10) === GBEMU_0x10 ? 0 : GBEMU_0x80;
                    parentObj.gfxBackgroundCHRBankPosition = (data & GBEMU_0x08) === GBEMU_0x08 ? GBEMU_0x400 : 0;
                    parentObj.gfxSpriteNormalHeight = (data & GBEMU_0x04) === 0;
                    parentObj.gfxSpriteShow = (data & GBEMU_0x02) === GBEMU_0x02;
                    parentObj.bgEnabled = (data & GBEMU_0x01) === GBEMU_0x01;
                    parentObj.memory[GBEMU_0xFF40] = data;
                }
            };
            this.memoryHighWriter[GBEMU_0x40] = this.memoryWriter[GBEMU_0xFF40];
            this.memoryWriter[GBEMU_0xFF41] = (parentObj, address, data) => {
                parentObj.lycMatchTriggerSTAT = (data & GBEMU_0x40) === GBEMU_0x40;
                parentObj.mode2TriggerSTAT = (data & GBEMU_0x20) === GBEMU_0x20;
                parentObj.mode1TriggerSTAT = (data & GBEMU_0x10) === GBEMU_0x10;
                parentObj.mode0TriggerSTAT = (data & GBEMU_0x08) === GBEMU_0x08;
                parentObj.memory[GBEMU_0xFF41] = data & GBEMU_0x78;
                if ((!parentObj.usedBootrom || !parentObj.usedGBCBootrom) && parentObj.lcdIsOn && parentObj.modeSTAT < GBEMU_2) {
                    parentObj.interruptsRequested |= GBEMU_0x2;
                    parentObj.checkIRQMatching();
                }
            };
            this.memoryHighWriter[GBEMU_0x41] = this.memoryWriter[GBEMU_0xFF41];
            this.memoryWriter[GBEMU_0xFF46] = (parentObj, addressTemp, dataTemp) => {
                parentObj.memory[GBEMU_0xFF46] = dataTemp;
                let data = dataTemp;
                let address = addressTemp;
                if (data > GBEMU_0x7F && data < GBEMU_0xE0) {
                    //DMG cannot DMA from the rom banks.
                    data <<= GBEMU_8;
                    address = GBEMU_0xFE00;
                    let stat = parentObj.modeSTAT;
                    parentObj.modeSTAT = 0;
                    let newData = 0;
                    do {
                        newData = parentObj.memoryReader[data](parentObj, data++);
                        if (newData !== parentObj.memory[address]) {
                            //JIT the graphics render queue:
                            parentObj.modeSTAT = stat;
                            parentObj.graphicsJIT();
                            parentObj.modeSTAT = 0;
                            parentObj.memory[address++] = newData;
                            break;
                        }
                        address += 1;
                    } while (address < GBEMU_0xFEA0);
                    if (address < GBEMU_0xFEA0) {
                        do {
                            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
                            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
                            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
                            parentObj.memory[address++] = parentObj.memoryReader[data](parentObj, data++);
                        } while (address < GBEMU_0xFEA0);
                    }
                    parentObj.modeSTAT = stat;
                }
            };
            this.memoryHighWriter[GBEMU_0x46] = this.memoryWriter[GBEMU_0xFF46];
            this.memoryWriter[GBEMU_0xFF47] = (parentObj, address, data) => {
                if (parentObj.memory[GBEMU_0xFF47] !== data) {
                    parentObj.midScanLineJIT();
                    parentObj.updateGBBGPalette(data);
                    parentObj.memory[GBEMU_0xFF47] = data;
                }
            };
            this.memoryHighWriter[GBEMU_0x47] = this.memoryWriter[GBEMU_0xFF47];
            this.memoryWriter[GBEMU_0xFF48] = (parentObj, address, data) => {
                if (parentObj.memory[GBEMU_0xFF48] !== data) {
                    parentObj.midScanLineJIT();
                    parentObj.updateGBOBJPalette(0, data);
                    parentObj.memory[GBEMU_0xFF48] = data;
                }
            };
            this.memoryHighWriter[GBEMU_0x48] = this.memoryWriter[GBEMU_0xFF48];
            this.memoryWriter[GBEMU_0xFF49] = (parentObj, address, data) => {
                if (parentObj.memory[GBEMU_0xFF49] !== data) {
                    parentObj.midScanLineJIT();
                    parentObj.updateGBOBJPalette(GBEMU_4, data);
                    parentObj.memory[GBEMU_0xFF49] = data;
                }
            };
            this.memoryHighWriter[GBEMU_0x49] = this.memoryWriter[GBEMU_0xFF49];
            this.memoryWriter[GBEMU_0xFF4D] = (parentObj, address, data) => {
                parentObj.memory[GBEMU_0xFF4D] = data;
            };
            this.memoryHighWriter[GBEMU_0x4D] = this.memoryWriter[GBEMU_0xFF4D];
            this.memoryHighWriter[GBEMU_0x4F] = this.cartIgnoreWrite;
            this.memoryWriter[GBEMU_0xFF4F] = this.cartIgnoreWrite; //Not writable in DMG mode.
            this.memoryHighWriter[GBEMU_0x55] = this.cartIgnoreWrite;
            this.memoryWriter[GBEMU_0xFF55] = this.cartIgnoreWrite;
            this.memoryHighWriter[GBEMU_0x68] = this.cartIgnoreWrite;
            this.memoryWriter[GBEMU_0xFF68] = this.cartIgnoreWrite;
            this.memoryHighWriter[GBEMU_0x69] = this.cartIgnoreWrite;
            this.memoryWriter[GBEMU_0xFF69] = this.cartIgnoreWrite;
            this.memoryHighWriter[GBEMU_0x6A] = this.cartIgnoreWrite;
            this.memoryWriter[GBEMU_0xFF6A] = this.cartIgnoreWrite;
            this.memoryHighWriter[GBEMU_0x6B] = this.cartIgnoreWrite;
            this.memoryWriter[GBEMU_0xFF6B] = this.cartIgnoreWrite;
            this.memoryHighWriter[GBEMU_0x6C] = this.cartIgnoreWrite;
            this.memoryWriter[GBEMU_0xFF6C] = this.cartIgnoreWrite;
            this.memoryHighWriter[GBEMU_0x70] = this.cartIgnoreWrite;
            this.memoryWriter[GBEMU_0xFF70] = this.cartIgnoreWrite;
            this.memoryHighWriter[GBEMU_0x74] = this.cartIgnoreWrite;
            this.memoryWriter[GBEMU_0xFF74] = this.cartIgnoreWrite;
        }
    }
    recompileBootIOWriteHandling() {
        //debugLog('This is recompileBootIOWriteHandling');
        //Boot I/O Registers:
        if (this.inBootstrap) {
            this.memoryWriter[GBEMU_0xFF50] = (parentObj, address, data) => {
                //debugLog('Boot rom reads blocked: Bootstrap process has ended.')
                parentObj.inBootstrap = false;
                parentObj.disableBootrom();
                parentObj.memory[GBEMU_0xFF50] = data;
            };
            this.memoryHighWriter[GBEMU_0x50] = this.memoryWriter[GBEMU_0xFF50];
            if (this.cGBC) {
                this.memoryWriter[GBEMU_0xFF6C] = (parentObj, address, data) => {
                    if (parentObj.inBootstrap) {
                        parentObj.cGBC = (data & GBEMU_0x1) === 0;
                        //Exception to the GBC identifying code:
                        if (parentObj.name + parentObj.gameCode + parentObj.rom[GBEMU_0x143] === 'Game and Watch 50') {
                            parentObj.cGBC = true;
                            cout('Created a boot exception for Game and Watch Gallery GBEMU_2 (GBC ID byte is wrong on the cartridge).', 1);
                        }
                        cout('Booted to GBC Mode: ' + parentObj.cGBC, 0);
                    }
                    parentObj.memory[GBEMU_0xFF6C] = data;
                };
                this.memoryHighWriter[GBEMU_0x6C] = this.memoryWriter[GBEMU_0xFF6C];
            }
        }
        else {
            //Lockout the roms from accessing the BOOT rom control register:
            this.memoryHighWriter[GBEMU_0x50] = this.cartIgnoreWrite;
            this.memoryWriter[GBEMU_0xFF50] = this.cartIgnoreWrite;
        }
    }
    toTypedArray(baseArray, memtype) {
        if (baseArray === null || baseArray.length === 0) {
            return new Int32Array();
        }
        let length = baseArray.length;
        let typedArrayTemp = new Uint8Array();
        switch (memtype) {
            case 'uint8':
                typedArrayTemp = new Uint8Array(length);
                break;
            case 'int8':
                typedArrayTemp = new Int8Array(length);
                break;
            case 'int32':
                typedArrayTemp = new Int32Array(length);
                break;
            case 'float32':
                typedArrayTemp = new Float32Array(length);
            default:
                break;
        }
        for (let index = 0; index < length; index++) {
            typedArrayTemp[index] = baseArray[index];
        }
        return typedArrayTemp;
    }
    fromTypedArray(baseArray) {
        if (!baseArray || !baseArray.length) {
            return new Int8Array();
        }
        let arrayTemp = new Int8Array();
        for (let index = 0; index < baseArray.length; ++index) {
            arrayTemp[index] = baseArray[index];
        }
        return arrayTemp;
    }
    getTypedArray(length, defaultValue, numberType) {
        let arrayHandle = new Int8Array();
        if (settings[GBEMU_5]) {
            for (let i = 0; i < length; i++) {
                arrayHandle[i] = defaultValue;
            }
            return arrayHandle;
        }
        switch (numberType) {
            case 'int8':
                arrayHandle = new Int8Array(length);
                break;
            case 'uint8':
                arrayHandle = new Uint8Array(length);
                break;
            case 'int32':
                arrayHandle = new Int32Array(length);
                break;
            case 'float32':
                arrayHandle = new Float32Array(length);
            default:
                break;
        }
        if (defaultValue !== 0) {
            let index = 0;
            while (index < length) {
                arrayHandle[index++] = defaultValue;
            }
        }
        return arrayHandle;
    }
}
// End of js/GameBoyCore.js file.
// Start of js/GameBoyIO.js file.
let gameboy = null;
let gbRunInterval = null; //GameBoyCore Timer
let settings = [
    //Some settings.
    true, //Turn on sound.
    false, //Boot with boot rom first? (set to false for benchmarking)
    false, //Give priority to GameBoy mode
    [GBEMU_39, GBEMU_37, GBEMU_38, GBEMU_40, GBEMU_88, GBEMU_90, GBEMU_16, GBEMU_13], //Keyboard button map.
    true, //Colorize GB mode?
    false, //Disallow typed arrays?
    GBEMU_4, //Interval for the emulator loop.
    GBEMU_15, //Audio buffer minimum span amount over x interpreter iterations.
    GBEMU_30, //Audio buffer maximum span amount over x interpreter iterations.
    false, //Override to allow for MBC1 instead of rom only (compatibility for broken 3rd-party cartridges).
    false, //Override MBC RAM disabling and always allow reading and writing to the banks.
    false, //Use the GameBoy boot rom instead of the GameBoy Color boot rom.
    false, //Scale the canvas in JS, or let the browser scale the canvas?
    GBEMU_0x10, //Internal audio buffer pre-interpolation factor.
    1 //Volume level set.
];
function start(canvas, rom) {
    //debugLog('This is start');
    clearLastEmulation();
    gameboy = new GameBoyCore(canvas, rom);
    gameboy.openMBC = openSRAM;
    gameboy.openRTC = openRTC;
    gameboy.start();
    run();
}
function run() {
    //debugLog('This is run')
    if (gameBoyEmulatorInitialized()) {
        if (!gameBoyEmulatorPlaying()) {
            gameboy.stopEmulator &= 1;
            cout('Starting the iterator.', 0);
            let dateObj = new Date(); // The line is changed for benchmarking.
            gameboy.firstIteration = dateObj.getTime();
            gameboy.iterations = 0;
        }
        else {
            cout('The GameBoy core is already running.', 1);
        }
    }
    else {
        cout('GameBoy core cannot run while it has not been initialized.', 1);
    }
}
function pausePlay() {
    if (gameBoyEmulatorInitialized()) {
        if (gameBoyEmulatorPlaying()) {
            clearLastEmulation();
        }
        else {
            cout('GameBoy core has already been paused.', 1);
        }
    }
    else {
        cout('GameBoy core cannot be paused while it has not been initialized.', 1);
    }
}
function clearLastEmulation() {
    if (gameBoyEmulatorInitialized() && gameBoyEmulatorPlaying()) {
        gameboy.stopEmulator |= GBEMU_2;
        cout('The previous emulation has been cleared.', 0);
    }
    else {
        cout('No previous emulation was found to be cleared.', 0);
    }
}
function openSRAM(filename) {
    return [];
}
function openRTC(filename) {
    return [];
}
function gameBoyEmulatorInitialized() {
    return typeof gameboy === 'object' && gameboy !== null;
}
function gameBoyEmulatorPlaying() {
    return (gameboy.stopEmulator & GBEMU_2) === 0;
}
//The emulator will call this to sort out the canvas properties for (re)initialization.
function initNewCanvas() {
    if (gameBoyEmulatorInitialized()) {
        gameboy.canvas.width = gameboy.canvas.clientWidth;
        gameboy.canvas.height = gameboy.canvas.clientHeight;
    }
}
// Start of realtime.js file.
// ROM code from Public Domain LPC2000 Demo 'realtime' by AGO.
let gameboyRom = 'r+BPyZiEZwA+AeBPySAobeEq6gAgKlYj5WJv6SRmZjjhKuXqACDJ/////////////////////////////////xgHZwCYhGcA2fX6/3/1xdXlIRPKNgHN9f/h0cHx6gAg+hLKtyAC8cnwgLcoF/CC7hjgUT6Q4FOv4FLgVOCAPv/gVfHZ8IG3IALx2fBA7gjgQA8PD+YB7gHgT/CC4FHuEOCCPojgU6/gUuBU4IE+/uBV4ID6NMs86jTL8dkKCgoKbWFkZSBieSBhZ28uIGVtYWlsOmdvYnV6b3ZAeWFob28uY29tCnVybDogc3BlY2N5LmRhLnJ1CgoKCv///////wDDSgnO7WZmzA0ACwNzAIMADAANAAgRH4iJAA7czG7m3d3Zmbu7Z2NuDuzM3dyZn7u5Mz5BR08nUyBSRUFMVElNRSCAAAAAAgEDADMBSTQeIUD/y37I8P/1y4fg//BE/pEg+su+8eD/yT7A4EY+KD0g/cnF1eWvEQPK1RITEhMGAyEAyuXFTgYAIWAMCQkqEhMqEhPB4SMFIOrhrwYIzYsU4dHByf////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAgMFBggJCwwOEBETFBYXGBobHR4fISIjJSYnKSorLC0uLzAxMjM0NTY3ODg5Ojo7PDw9PT4+Pj8/Pz9AQEBAQEBAQEBAPz8/Pz4+PT08PDs7Ojk5ODc2NTU0MzIxMC8uLCsqKSgmJSQjISAfHRwaGRcWFRMSEA8NCwoIBwUEAgH//fz6+ff29PPx8O7t6+ro5+Xk4uHg3t3c2tnY19bU09LR0M/OzczLysnJyMfGxsXFxMPDw8LCwcHBwcDAwMDAwMDAwMDBwcHBwsLDw8PExcXGxsfIycnKy8zNzs/Q0dLT1NXX2Nna3N3e4OHi5OXn6Onr7O7v8fL09vf5+vz9AAEECRAZJDFAUWR5kKnE4QAhRGmQueQRQHGk2RBJhMEAQYTJEFmk8UCR5DmQ6UShAGHEKZD5ZNFAsSSZEIkEgQCBBIkQmSSxQNFk+ZApxGEAoUTpkDnkkUDxpFkQyYRBAMGESRDZpHFAEeS5kGlEIQDhxKmQeWRRQDEkGRAJBAEAAQQJEBkkMUBRZHmQqcThACFEaZC55BFAcaTZEEmEwQBBhMkQWaTxQJHkOZDpRKEAYcQpkPlk0UCxJJkQiQSBAIEEiRCZJLFA0WT5kCnEYQChROmQOeSRQPGkWRDJhEEAwYRJENmkcUAR5LmQaUQhAOHEqZB5ZFFAMSQZEAkEAQAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAgICAgIDAwMDBAQEBAUFBQUGBgYHBwcICAkJCQoKCgsLDAwNDQ4ODw8QEBEREhITExQUFRUWFxcYGRkaGhscHB0eHh8gISEiIyQkJSYnJygpKisrLC0uLzAxMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OT1FSU1RVVldZWltcXV9gYWJkZWZnaWprbG5vcHJzdHZ3eXp7fX5/gYKEhYeIiouNjpCRk5SWl5manJ2foKKkpaepqqytr7GytLa3ubu9vsDCxMXHycvMztDS1NXX2dvd3+Hi5Obo6uzu8PL09vj6/P4A//z38Ofcz8CvnIdwVzwfAN+8l3BHHO/Aj1wn8Ld8PwC/fDfwp1wPwG8cx3AXvF8AnzzXcAecL8BP3Gfwd/x/AH/8d/Bn3E/AL5wHcNc8nwBfvBdwxxxvwA9cp/A3fL8AP3y38Cdcj8DvHEdwl7zfAB88V3CHnK/Az9zn8Pf8/wD//Pfw59zPwK+ch3BXPB8A37yXcEcc78CPXCfwt3w/AL98N/CnXA/AbxzHcBe8XwCfPNdwB5wvwE/cZ/B3/H8Af/x38GfcT8AvnAdw1zyfAF+8F3DHHG/AD1yn8Dd8vwA/fLfwJ1yPwO8cR3CXvN8AHzxXcIecr8DP3Ofw9/z/AP/////////////////////+/v7+/v79/f39/fz8/Pz8+/v7+vr6+vn5+fj4+Pf39/b29fX19PTz8/Ly8fHw8PDv7u7t7ezs6+vq6uno6Ofn5uXl5OPj4uHh4N/e3t3c3Nva2djY19bV1NTT0tHQz8/OzczLysnIx8bFxMPCwcDAvr28u7q5uLe2tbSzsrGwr62sq6qpqKalpKOioJ+enZyamZiWlZSTkZCPjYyLiYiHhYSCgYB+fXt6eHd1dHJxcG5sa2loZmVjYmBfXVtaWFdVU1JQTk1LSUhGREJBPz08Ojg2NDMxLy0rKigmJCIgHx0bGRcVExEPDQsJBwUDAf9/Px8PBwMBgEAgEAgEAgEAAQEBAQEBAQEBAQEA//////////////+AEAcAAQABAAEBAAEBAAEA/wD//wD//wD/AP+AKwcBAAEAAQD/AP8A/wD/AP8A/wABAAEAAQCARgcBAQEBAQD//////////////wABAQEBAQGAYQf///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+AwODw+Pz+/xEAwAGxwj4E9cU+BfUKbwMKZ37+gCALI34LAiN+AwILGOsahhIDHBwcHPE9IN7BIRAAGVRdPgX1Cm8DCmcalhIjfAILfQIDAx0dHR3xPSDnIRgAGVRd8T0grskRAcAB6cI+BPUKbwMKZ37+gCALI34LAiN+AwILGOs+CvUahhIcHBwc8T0g9CN8Agt9AgMD8T0g0MkgIEZJTExFRCAgIFBPTFlHT05TIEhFTElDT1BURVJJTiBBQ1RJT04gIQDADgpwLHQsGhPWICI2ACwNIPE+oOoQyngBCQDlYmsJVF3hDMYKR3AsdCwaG9YgIjYALA0g8a/qEcrJ+hDK/jDI1gTqEMpHPqCQ/lA4Aj5QDgAM1ggw+3ghAcARBAB3xggZDSD5+hHKg+oRykf+UDgCPlAOAAzWCDD7eC4td9YIGQ0g+ckh9grzMf/PzVABr+Am4P/gD+BD4EL2SOBFPkDgQT4E4AfN9RM+CuoAAA4HeeBwJqCvIstsKPsNIPIh/v8yy30g+wEKABH1/yFpAc3kE+cCAVYAEQDBIVt2zeQTrwYYIWsOzYsUIYsOzaQUxwGwAxEAgCGhF8XlzeQT4cERAIjN5BMhAJgRAwABYMDHcc9yIwUg+BQdIPHN9RMhuxUGAc2WE82JEz5E4EGv4EU+A+D/+z4B6hLK4E0QAAB4zccTBSD6zZATxwEACFkhAIhzIwt4sSD5IQDHPv9FdyRwJCJ3JXclcCwg8x5/IQCYx3PPNgDL1DYIx3PLlCPLVCjuPoABDxARIAAhIpjF5XfL1HfLlDwZDSD1POEswQUg7D486jPLr+o0yz3qL8s+oOCCPgLqG8vNiRM+ROBBr+BFPgPg/68+ACEXyyI+CiI+IHev6h7L4ITgluodyz4B6h/L6g/D6g3KBlARnAjNxAjNcwsBLAHFzTsLzQAJwQt4sSDzzZATxwEACFkhAIhzIwt4sSD5zfUTeQYQIYMOzYsUPv/qKcsGgBGwCM3ECM2JEwEsAcXNbAzNAAnBC3ixIPOv6hLKzZATPpDgU/PHAbADEQCIIaEXzeQTzfUTIQIWBgHNlhPNiRM+ROBBr+BFPgPg//sY/j4D6gAgzcRGBgMhF8t+gCJ+gDwifoB3zckP+jDLb/oxy2fNtgs+AeCB8IG3IPv6Dcq3KAPNcwHJ+h3LBgARTg2Hb2AZKmZvTgkq4ItfKjzgjD1PKuCNe4eHg0cRAMUqEhwFIPp5h4eBRxEAxCoSHAUg+n3qMMt86jHLyfCL4I7wjOCP8I3gkBEAw9XlzcoQ4dHwpeaAEhwBAwAJ8JA94JAg6CEAxQYPKk+gXxq3IB95yzegXxq3IBYqT6BfGrcgD3nLN6BfGrcgBiwsLBhHLOXNyhDwlrcoKwYB8KXGP0/LfygBBcXwpMY/Vx4AzZMOe8H18KPGP1ceAM2TDsHhJCJwGAzhJPCjxj8i8KTGPyIsJRbDBg/wjj3gjsLiCz4C6gAgw1JhfBjcHwAL7mpIYL9vBgMhF8t+gCJ+gDwifoB3zckPIcsNEQDGzf4MI+U+A+oAICEgy83+DPocy9YIb+ocy82vYAYDESDLIWIOxeXVzcoQ4fCjxhQi8KQiNg8jVF3hIyMjwQUg5M3ERsE+AeoAIAr+/ygiEQDGbyYAKRnlAwoDbyYAKRleI1bhKmZvxc0xHMwAQMEY2T4B4IHwgbcg+8l+PMjl1c3KEAYB8KVPy38oAQXF8KTLf/UoAi88Vx4AzZMO8XsgAi88xn/B9fCjy3/1KAIvPFceAM2TDvF7KAIvPMZ/wdESE3gSE+EjIyMYsFANAgAIDAYCRCgoFANEKAAUE0QAABQSRAAoFAJVKCjsA1UoAOwTVQAA7BJVACjsAAAEBQAAAAEFAAEBAwIGAQEDBwYCAgAHAwICAAcEAwMBAgYDAwEFBgQEAAECBAQAAwIFBQQFBgUFBAcGMgAAzgAAADIAAM4AAAAyAADOKAAAHhEAChEAAAAACu8AHu8AFAAKFAD2FAAPCgAF6AAC4gAQ3gAQ4gD+CgD74g4C3Q4C4QAC4vIC3fIC4AAM4PsM4PsQ4/sJ3fsJ/wABAQICAwMEBAUFAAAGAQYCBgMGBAYFBgAHAQcCBwMHBAcFBwYICQoKCwsMDA0NDgoPDxAQEQoSEhMTERQVFRYVFxUYCBkIGggb/yAAD/AbD/DlD/9//3+XEQAAAGD/f5cRAAAYAP9/lxEAAIB8lxH/f/9/QHz/f18IAADLI8sSeC9HeS9PAyEAAH2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEn2Pb3yPZwk4BWd9kW+3yxPLEssoyxkJ0BPJ+hfLJgJvfuCcLzzgnn3GQG9+4Jvgn6/gmOCZ4JrgneChPkDgl/oYy29OfcZAb0bFeOCgeeCizdMQ8KPgpvCk4KnwpeCsr+Cg4KI+QOChzdMQ8KPgp/Ck4KrwpeCtwXkvPOCgr+CheOCizdMQ8KPgmfCk4JzwpeCf8Kbgl/Cp4JrwrOCd8KfgmPCq4JvwreCe+hnLJgJvTn3GQG9GxXjgoHkvPOChr+CizdMQ8KPgpvCk4KnwpeCswXngoHjgoa/gos3TEPCj4KfwpOCq8KXgra/goOChPkDgos3TEPCj4JnwpOCc8KXgn/Cm4JfwqeCa8KzgnfCn4JjwquCb8K3gnskq4KAq4KEq4KLwl1/woCYGV8t6ICDLe3soJy88X3qTMAIvPG96g1YlXiVvfiVuZxl8LzwYH3ovPFfLeyjhey88X5IwAi88b3qDViVeJW9+JW5nGXxH8Jhf8KEmBlfLeiAgy3t7KCcvPF96kzACLzxveoNWJV4lb34lbmcZfC88GB96LzxXy3so4XsvPF+SMAIvPG96g1YlXiVvfiVuZxl8T/CZX/CiJgZXy3ogIMt7eygnLzxfepMwAi88b3qDViVeJW9+JW5nGXwvPBgfei88V8t7KOF7LzxfkjACLzxveoNWJV4lb34lbmcZfICB4KPwml/woCYGV8t6ICDLe3soJy88X3qTMAIvPG96g1YlXiVvfiVuZxl8LzwYH3ovPFfLeyjhey88X5IwAi88b3qDViVeJW9+JW5nGXxH8Jtf8KEmBlfLeiAgy3t7KCcvPF96kzACLzxveoNWJV4lb34lbmcZfC88GB96LzxXy3so4XsvPF+SMAIvPG96g1YlXiVvfiVuZxl8T/CcX/CiJgZXy3ogIMt7eygnLzxfepMwAi88b3qDViVeJW9+JW5nGXwvPBgfei88V8t7KOF7LzxfkjACLzxveoNWJV4lb34lbmcZfICB4KTwnV/woCYGV8t6ICDLe3soJy88X3qTMAIvPG96g1YlXiVvfiVuZxl8LzwYH3ovPFfLeyjhey88X5IwAi88b3qDViVeJW9+JW5nGXxH8J5f8KEmBlfLeiAgy3t7KCcvPF96kzACLzxveoNWJV4lb34lbmcZfC88GB96LzxXy3so4XsvPF+SMAIvPG96g1YlXiVvfiVuZxl8T/CfX/CiJgZXy3ogIMt7eygnLzxfepMwAi88b3qDViVeJW9+JW5nGXwvPBgfei88V8t7KOF7LzxfkjACLzxveoNWJV4lb34lbmcZfICB4KXJ9T6D4EDxyfWv4EDxyfXF1eXHKv7/KFD+FiAaTiMqh4eHVF1vJgApKXgGmAlHelRne11vGNzGYBLPeBIcGNN2ACETyjQ1KPc1yfvFBmR2AAUg+8HJ+3YABSD7yfXF1eUqEhMLeLEg+OHRwfHJxeUBAKAhAMDNAxThwcnF5XEjBSD74cHJxdXlAQCAIZXKzQMU4dHBycXV5a/qFcuwIAwaEyIaEzIEDXjqFcvlxRq+EyAPIxq+IAkTIw0gCMHhGBkrGyMjBSDmecFPBBoTIhoTIiEVyzThDSDS+hXL4dHBydVfzXIUuzD60cnF9cH6FMrLD6mAR/CLkR+AR/AFqOoUysHJ9cXltxcXF/aA4Ggq4GkFIPo+5OBH4cHxyfXF5bcXFxf2gOBqKuBrBSD6PuTgSOBJ4cHxyT4Q4ADwAC/LN+bwRz4g4ADwAC/mD7DqFsvJzyEAgK8GIE8+CCINIPwFIPnHIQCABiBPIg0g/AUg+cnFzQMVSs0eFcHJxc0RFUjNGRVLzSMVwcnFBgHNKxXBycUGABj2xQYDGPHFBgLNKxXByfXlh4eAJsBvceHxyfXlh4cmwG9GI04jXiNW4fHJ9cXV5eCDKjzK8BPWIF/wg835FF95xghPezwY6PXF1eXF1c13FdHBex4FIS3LGNUBKssR8NjNlRURGPzNlRURnP/NlRUR9v/NlRUR//8+LzwZOPwCA3ovV3svXxMZyTAwRlBT/zAwUE5UU/8wMExJTkVT/xYFB1dFTENPTUUgVE8WBQgtUkVBTFRJTUUtFgAJREVNTyBNQURFIEVTUEVDSUFMTFkWAQpGT1IgTENQJzIwMDAgUEFSVFn/FgAAR1JFRVRJTlg6ICAgICAgICAgICAWAAFEU0MsUEFOLFNBQixGQVRBTElUWRYAAkpFRkYgRlJPSFdFSU4sSUNBUlVTFgADRE9YLFFVQU5HLEFCWVNTICAgICAWAAQgICAgICAgICAgICAgICAgICAgIBYABUNSRURJVFM6ICAgICAgICAgICAgFgAGQUxMIEdGWCZDT0RFIEJZIEFHTyAWAAdIRUxJQ09QVEVSIDNEIE1PREVMIBYACENSRUFURUQgQlkgQlVTWSAgICAgFgAJICAgICAgICAgICAgICAgICAgICAWAApVU0VEIFNPRlRXQVJFOiAgICAgIBYAC1JHQkRTLE5PJENBU0gsRkFSICAgFgAMICAgICAgICAgICAgICAgICAgICAWAA1DT05UQUNUOiAgICAgICAgICAgIBYADkdPQlVaT1ZAWUFIT08uQ09NICAgFgAPSFRUUDovL1NQRUNDWS5EQS5SVSAWABAgICAgICAgICAgICAgICAgICAgIBYAEVNFRSBZT1UgT04gR0JERVYyMDAw/wAAAAAAAAAAAAAAAAAAAAAICBwUHBQ4KDgoMDBwUCAgKCh8VHxUKCgAAAAAAAAAABQUPip/QT4qfFT+gnxUKCgICDw0fkL8rP6Cfmr8hHhYJCR+Wn5SPCR4SPyU/LRISBgYPCR+Wjwkflr8tH5KNDQQEDgocFAgIAAAAAAAAAAABAQOChwUOCg4KDgoHBQICBAQOCgcFBwUHBQ4KHBQICAAABQUPio8NH5CPCx8VCgoAAAICBwUPDR+QjwsOCgQEAAAAAAAAAAAEBA4KHBQcFAAAAAAAAB8fP6CfHwAAAAAAAAAAAAAAAAwMHhIeEgwMAQEDgoeEjwkeEjwkOCgQEAYGDwkflr+qv6q/LR4SDAwGBg8JHxUPDQ4KHxs/oJ8fBwcPiJ+Wjw0eEj8vP6CfHwcHD4iflo8NE5K/LR4SDAwJCR+Wn5afFT8tP6CfGwQEBwcPiJ8XPyEfnr8tHhIMDAYGDwkeFj8pP66/LR4SDAwPDx+Qv66XFQ4KHBQcFAgIBwcPiJ+Wjwkflr8tPiIcHAcHD4iflr+sn5KfHT4iHBwAAAAAAgIHBQICBAQOCgQEAAACAgcFAgIEBA4KDgocFAAAAAAHBQ4KHBQcFA4KAAAAAAAADw8fkJ8fPyEeHgAAAAAAAA4KBwUHBQ4KHBQAAAYGDwkflr8tHhoEBA4KBAQHBw+In5a/rL8pPi4+IhwcBwcPiJ+Wv66/oL+uvy0SEg4OHxEflr8pP6a/LT4iHBwHBw+In5a5qbgoP6y/IxwcDAweEh8VH5a7qr+uvyEeHgcHD4ifFx8RHhY/Lz+gnx8HBw+Inxc/IT4uOCg4KBAQBwcPiJ+Wvy8/qL+uvyEeHgkJH5a/rr+gv66/LT8tEhIPDx+QjwsOChwUHhY/IR4eDw8fkI+Og4KXFT8tHhIMDAkJH5afFR+Qv66/LT8tEhIICBwUHBQ4KDkpP66fEQ4OCgofFR+Qv6q/rr8tPy0SEgkJH5a/pr+qv6y7qr8tEhIHBw+In5a7qruqvy0+IhwcBwcPiJ+Wv66/IT4uOCgQEAcHD4iflr+uv6q/LT+inZ2HBw+In5a/LT4iPy0/LRISBwcPiJ8XP6Cfnr8tPiIcHB8fP6CfGw4KHBQcFBwUCAgJCR+Wn5a7qruqvy0eEgwMERE7qruqnxUfFR4SHBQICAkJH5aflr+uv6q/KR8VCgoJCR+WnxUOCg8JH5a/LRISCQkflr8tPy0eEhwUHBQICA8PH5C/LT46Dwsflr8hHh4HBw+IjwsOChwUHhYfEQ4OEBA4KDwkHhIPCQeEg4KBAQ4OHxEPDQcFDgoeGj4iHBwGBg8JH5a7qpERAAAAAAAAAAAAAAAAAAAAAB8fP6CfHx81rdPfJJne5X1MAIvPEevyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxnLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEeRcvT/F5MAIvPIVvJrcBAAA+t7zLEbrLED6/vcsRu8sQPj+8P8sRuj/LEL0/yxG7P8sQeLHIeKHAebcgB3xiV31rX3jLH9L/HD5AlU97lW96lPUwAi88R6/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGTABgB/LGcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYV5Fy9P8XkwAi88hGcuQMMxHMsf0pcdPkCUT3qUZ3uV9TACLzxHr8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZMAGAH8sZyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhMsRyxeUMAGEyxHLF5QwAYTLEcsXlDABhHkXL0/xeTACLzyFbyZAwzEcyx/SoRt91r9PfZNvepT1MAIvPEevyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxnLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFyxHLF5UwAYXLEcsXlTABhcsRyxeVMAGFeRcvT/F5MAIvPIRnLr/DMRz//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////3q8MAVUZ3tdb3u90pdAfZNPepRfkTA+V3nLPy88g+CDPn+R5YdPbyYARCkpKQkBkVIJweV41kAXb3nWQB8fH+YPZ/CChGd55gcGB/YITwpP8INHLMl5S1+RV3nLPy88g+CDPneR5YdPbyYARCkpKQkBklsJweV41kAXb3nWQB8fH+YPZ/CChGd55gcGB/YITwpP8INHLMmVT3qUX5EwPld5yz8vPIPggz5/keWHT28mAEQpKSkJAR9BCcHleNZAF2951kAfHx/mD2fwgoRneeYHBgf2CE8KT/CDRyzJeUtfkVd5yz8vPIPggz53keWHT28mAEQpKSkJASBKCcHleNZAF2951kAfHx/mD2fwgoRneeYHBgf2CE8KT/CDRyzJfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkfrF3e8t4IAN6LCyAR8sJMAEkyX6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALH6xInvLeCAGessJMAEkgEcALMl+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASV+sXd7y3ggA3osLIBHywEwASXJfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsfrF3e8t4IAZ6ywEwASWARywsyf///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wHRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyLRe7o4A1pXewYHoE8K9XqgTwQK4JF6Hx8f5g9X8JNnTixGLXsfHx/mD1/wgoNne5LRxADB8JGiVy+mX3qhsyJ6L6ZfeqCzItF7ujgDWld7BgegTwr1eqBPBArgkXofHx/mD1fwk2dOLEYtex8fH+YPX/CCg2d7ktHEAMHwkaJXL6ZfeqGzInovpl96oLMi0Xu6OANaV3sGB6BPCvV6oE8ECuCReh8fH+YPV/CTZ04sRi17Hx8f5g9f8IKDZ3uS0cQAwfCRolcvpl96obMiei+mX3qgsyIxDsrh+eEWwxgNIf3Er+oLyuoMyiwsLPCPPcjgj14sGrcqKPDGeeCT+g3Ktygm+gvKPP4DIAI+AeoLyiAH+gzKPOoMyvoMyl8WyvCT1nkSe8bH4JMqTypHKuUmxl+Hh4M8PG8qX1Z5h4eBPDxveE4sh4eARjw8bypmb3y6OAViV31rX3y4OAVgR31pT3q4OAVQR3tZT3iU4JR8h+CV5dXFr+CSzUpifeCS0eHVzUpi0eE+AeCSzUpi8JRfPniTZy5Hr8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdMAGEH8sdxkBnCA7KMQDC5fCVb8l7vTBVfZNPepRfkTAkV3nLPy88Rz5/kU3Fh09vJgBEKSkJAfdiCcHlJsLwkm94BoDJeUtfkVd5yz8vPEc+d5FNxYdPbyYARCkpCQH4ZwnB5SbC8JJveAaAyZVPepRfkTAkV3nLPy88Rz5/kU3Fh09vJgBEKSkJAalsCcHlJsLwkm94BoDJeUtfkVd5yz8vPEc+d5FNxYdPbyYARCkpCQGqcQnB5SbC8JJveAaAyYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNg7gwBZOCcSwsDYO4MAWTgnEsLA2DuDAFk4JxLCwNyXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDXEsLIO4MAOTgg1xLCyDuDADk4INcSwsg7gwA5OCDcmDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDIO4MAWTgnEsLAyDuDAFk4JxLCwMg7gwBZOCcSwsDMlxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggxxLCyDuDADk4IMcSwsg7gwA5OCDHEsLIO4MAOTggzJxg+Hh+oawXovpl96obMiei+mX3qgszIkeRgAInAtJCJwLSQicC0kInAtJCJwLSQicC0kInAtJCJwLSQicC0kInAtJCJwLSQicC0kInAtJCJwLSQW/8n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+qqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQAhMwwzwAASABIzwDMMACEAITMMM8AAEgASM8AzDAAhACEzDDPAABIAEjPAMwwAIQj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINkI/Bh+Mv1k+8DvgedAsyDZCPwYfjL9ZPvA74HnQLMg2Qj8GH4y/WT7wO+B50CzINnMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzzMzMzDMzMzPMzMzMMzMzM8zMzMwzMzMzwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDMDAwMAMDAwMwMDAwAwMDAzAwMDADAwMDPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBDx8QEBAQEBAR8fEBAQEBAQ8fEBAQEBAQEfHxAQEBAQEPHxAQEBAQEBHx8QEBAQEBCqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlVVqqpVVaqqVVWqqlUC4XIscAl7InAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJcixwCXsicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCXIscAl7InAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJcixwCXsicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCXIscAl7InAJInAJInAJInAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAkicAkicAkicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJInAJInAJInAJcixwCXsicAkicAkicAkicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCXIscAl7InAJInAJInAJInAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAkicAkicAkicAkicAkicAkicAlyLHAJeyJwCSJwCSJwCSJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJcixwCXsicAkicAkicAkicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCXIscAl7InAJInAJInAJLCwly2XIJGjJycnJyeEicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAlyLHAJeyJwCSJwCSwsJctlyCRoycnJycnhInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJInAJcixwCXsicAksLCXLZcgkaMnJycnJ4SJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCSJwCXIscAl7LCwly2XIJGjJycnJydE+t5LI4IXmB8RSRPCFHx8focjlzTJE4XkicCwicCwicCwicCwicCwicCwicCwicCzJ+ABUXWhHeZAfyx1nATNZCfCCMQCv/qAoAzEAvwH/AOlHPgeQVF1HDjOvyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxkwAYAfyxlHIbRXCeViaz7/AQ8Ayfoay2/6G8uFZ/4UIAU+/y0YBtbsIAU8LOoby3zqGsvNr2AhlEbNyhDwpMagV/Cjxn9f1SGXRs3KEPCkxqBn8KPGf2/RzTEcKAsf2hhZH9oYWcPERny6OAViV31rX+XNmkbh1Xu90sxFe9ZA4Ih9k0884Il6lF/ghjzgij2RMGvgh3nLPy88g+CF8IIBDwBvVHzWQBfLN6GFZ3rmBxdvGAjwij3KAETgivCJX/CGV/CFGASCHSgLy38g+Ffwh4LghR3NYkUY2nvgifCIg1/l5gf2CG8mB1Z7aB8fHx/LHR/LHeYDxkBnrx7/6XnghpPgh3vLPy88geCF8IIBDwBvVHzWQBfLN6GFZ3rmBxdv8Ilf8IZX8IXLfyAHV/CHgh0YAYLghc1iRfCKPcoAROCKGN171kDgiHuVTzzgiXqUX+CGPOCKPZEwa+CHecs/LzyD4IXwggEPAG9UfNZAF8s3oYVneuYHF28YCPCKPcoAROCK8Ilf8IZX8IUYBIIdKAvLfyD4V/CHguCFHc0qRhjae+CJ8IiTX+XmB/YQbyYHVntoHx8fH8sdH8sd5gPGQGc+/1jpeeCGk+CHe8s/LzyB4IXwggEPAG9UfNZAF8s3oYVneuYHF2/wiV/whlfwhct/IAdX8IeCHRgBguCFzSpG8Io9ygBE4IoY3UYAALoAAHzWQMhPHx8f5h9HeeYHKAsE/gUwBvUhylblBT4PkCHJRoRn5fCCZ69vyfCCZ69vIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIsnxAQ8APcqEVz0odj0oOj0idwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwksLCXLZSgCJGgidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwksLCXLZSgCJGgidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwksLCXLZSgCJGgidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkidwkid8kicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAksLCUicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAkicAloyfgAVF3wgjEAr/6gKAMxAL8B/wDFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcVia/nJJgJ+4JovPOCYfcZAb37gl+Cbr+CZ4JzgneCePkDgn8n/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Aw==';
class ArrayObject {
    constructor() {
        this.array = new Int32Array();
    }
}
function debugLog(str) {
    let isLog = false;
    if (isLog) {
        console.log(str);
    }
}
function gbemuRunIteration() {
    let start = Date.now();
    let benchmark = new Benchmark();
    benchmark.setupGameboy();
    for (let i = 0; i < GBEMU_20; ++i) {
        benchmark.runGameboy();
    }
    benchmark.tearDownGameboy();
    let end = Date.now();
    console.log('gbemu: ms = ' + String((end - start)));
}
gbemuRunIteration();
